const { getDatabase } = require('../config/database');

class Risk {
    static migrate() {
        const db = getDatabase();
        db.exec(`
            CREATE TABLE IF NOT EXISTS risks (
                id           INTEGER PRIMARY KEY AUTOINCREMENT,
                source       TEXT NOT NULL DEFAULT 'manual'
                             CHECK(source IN ('manual','auto')),
                source_type  TEXT NOT NULL DEFAULT 'manual',
                external_id  TEXT,
                title        TEXT NOT NULL,
                description  TEXT,
                category     TEXT NOT NULL DEFAULT 'Sonstiges',
                probability  INTEGER NOT NULL DEFAULT 3 CHECK(probability BETWEEN 1 AND 5),
                impact       INTEGER NOT NULL DEFAULT 3 CHECK(impact BETWEEN 1 AND 5),
                status       TEXT NOT NULL DEFAULT 'offen'
                             CHECK(status IN ('offen','in_bearbeitung','akzeptiert','behoben')),
                responsible  TEXT,
                mitigation   TEXT,
                due_date     TEXT,
                metadata     TEXT,
                last_synced  TEXT,
                created_at   TEXT NOT NULL DEFAULT (datetime('now')),
                updated_at   TEXT NOT NULL DEFAULT (datetime('now'))
            );
            CREATE UNIQUE INDEX IF NOT EXISTS risks_external_id ON risks(source_type, external_id)
                WHERE external_id IS NOT NULL;
        `);
        // Migration: add metadata column to existing tables
        try { db.exec(`ALTER TABLE risks ADD COLUMN metadata TEXT`); } catch {}
    }

    static _parse(row) {
        if (!row) return null;
        if (row.metadata) {
            try { row.metadata = JSON.parse(row.metadata); } catch { row.metadata = null; }
        }
        return row;
    }

    static getAll({ category, status, source } = {}) {
        const db = getDatabase();
        const where = [];
        const vals = [];
        if (category) { where.push('category = ?'); vals.push(category); }
        if (status)   { where.push('status = ?');   vals.push(status); }
        if (source)   { where.push('source = ?');   vals.push(source); }
        const rows = db.prepare(
            `SELECT *, (probability * impact) as score FROM risks
             ${where.length ? 'WHERE ' + where.join(' AND ') : ''}
             ORDER BY (probability * impact) DESC, created_at DESC`
        ).all(...vals);
        return rows.map(r => this._parse(r));
    }

    static getById(id) {
        return this._parse(getDatabase().prepare(
            'SELECT *, (probability * impact) as score FROM risks WHERE id = ?'
        ).get(id));
    }

    static create(fields) {
        const db = getDatabase();
        const r = db.prepare(`
            INSERT INTO risks (source, source_type, external_id, title, description, category, probability, impact, status, responsible, mitigation, due_date, metadata, last_synced)
            VALUES (@source, @source_type, @external_id, @title, @description, @category, @probability, @impact, @status, @responsible, @mitigation, @due_date, @metadata, @last_synced)
        `).run({
            source:      fields.source      ?? 'manual',
            source_type: fields.source_type ?? 'manual',
            external_id: fields.external_id ?? null,
            title:       fields.title,
            description: fields.description ?? null,
            category:    fields.category    ?? 'Sonstiges',
            probability: fields.probability ?? 3,
            impact:      fields.impact      ?? 3,
            status:      fields.status      ?? 'offen',
            responsible: fields.responsible ?? null,
            mitigation:  fields.mitigation  ?? null,
            due_date:    fields.due_date    ?? null,
            metadata:    fields.metadata ? JSON.stringify(fields.metadata) : null,
            last_synced: fields.last_synced ?? null,
        });
        return this.getById(r.lastInsertRowid);
    }

    static upsertAuto({ source_type, external_id, title, description, category, probability, impact, metadata }) {
        const db = getDatabase();
        const existing = db.prepare(
            'SELECT id FROM risks WHERE source_type = ? AND external_id = ?'
        ).get(source_type, external_id);
        const now = new Date().toISOString();
        const metaStr = metadata ? JSON.stringify(metadata) : null;
        if (existing) {
            db.prepare(`
                UPDATE risks SET title=?, description=?, probability=?, impact=?, metadata=?, last_synced=?, updated_at=datetime('now')
                WHERE id=?
            `).run(title, description, probability, impact, metaStr, now, existing.id);
            return this.getById(existing.id);
        }
        return this.create({ source: 'auto', source_type, external_id, title, description, category, probability, impact, metadata, last_synced: now });
    }

    static update(id, fields) {
        const db = getDatabase();
        const allowed = ['title','description','category','probability','impact','status','responsible','mitigation','due_date'];
        const setClauses = [];
        const vals = [];
        for (const key of allowed) {
            if (fields[key] !== undefined) {
                setClauses.push(`${key} = ?`);
                vals.push(fields[key]);
            }
        }
        if (!setClauses.length) return this.getById(id);
        setClauses.push("updated_at = datetime('now')");
        vals.push(id);
        db.prepare(`UPDATE risks SET ${setClauses.join(', ')} WHERE id = ?`).run(...vals);
        return this.getById(id);
    }

    static delete(id) {
        return getDatabase().prepare('DELETE FROM risks WHERE id = ?').run(id).changes > 0;
    }

    static getStats() {
        const db = getDatabase();
        const all = db.prepare('SELECT probability * impact as score, status, source FROM risks').all();
        return {
            total:    all.length,
            kritisch: all.filter(r => r.score >= 20).length,
            hoch:     all.filter(r => r.score >= 12 && r.score < 20).length,
            mittel:   all.filter(r => r.score >= 6  && r.score < 12).length,
            niedrig:  all.filter(r => r.score < 6).length,
            behoben:  all.filter(r => r.status === 'behoben').length,
            auto:     all.filter(r => r.source === 'auto').length,
        };
    }
}

module.exports = Risk;
