const Anthropic = require('@anthropic-ai/sdk');
const { getDatabase } = require('../config/database');

let client = null;

function getClient() {
    if (!client) {
        if (!process.env.ANTHROPIC_API_KEY) {
            throw new Error('ANTHROPIC_API_KEY ist nicht konfiguriert');
        }
        client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
    }
    return client;
}

const BASE_SYSTEM_PROMPT = `Du bist ein IT-Support-Assistent für Cereda Systems GmbH.
Du hilfst IT-Mitarbeitern bei der Analyse von Support-Tickets und der Lösungsfindung.
Antworte immer auf Deutsch, sei präzise und praxisorientiert.
Nutze keine unnötigen Floskeln.`;

const USER_SYSTEM_PROMPT = `Du bist ein freundlicher IT-Hilfe-Assistent für Mitarbeiter der Cereda Systems GmbH.
Du hilfst Benutzern bei alltäglichen IT-Problemen (Windows, Office, Drucker, Passwörter, WLAN, E-Mail usw.).
Antworte immer auf Deutsch, in einfacher verständlicher Sprache ohne unnötige Fachbegriffe.
Gib konkrete, schrittweise Anleitungen. Sei geduldig und freundlich.
Wenn du ein Problem nicht lösen kannst oder wenn es zu komplex ist, empfehle dem Benutzer freundlich, ein Support-Ticket zu erstellen – er kann das direkt über das Portal tun.`;

/**
 * Analysiert ein Ticket und gibt Kategorie, Priorität und ersten Lösungsvorschlag zurück.
 * @param {string} title
 * @param {string} description
 * @returns {{ category: string, priority: string, suggestion: string }}
 */
async function analyzeTicket(title, description) {
    const prompt = `Analysiere dieses IT-Support-Ticket und antworte NUR mit einem validen JSON-Objekt:

{
  "category": "<Software|Hardware|Allgemein|SelectLine>",
  "priority": "<niedrig|mittel|hoch|kritisch>",
  "suggestion": "<Erster konkreter Lösungsvorschlag in 2-4 Sätzen>"
}

Regeln für Priorität:
- kritisch: System komplett ausgefallen, mehrere Benutzer betroffen, Produktionsausfall
- hoch: Wichtige Funktion defekt, ein Benutzer komplett blockiert
- mittel: Eingeschränkte Funktion, Workaround möglich
- niedrig: Kosmetisches Problem, Wunsch/Verbesserung

Ticket-Titel: ${title}
Ticket-Beschreibung: ${description || '(keine Beschreibung angegeben)'}`;

    const message = await getClient().messages.create({
        model: 'claude-sonnet-4-6',
        max_tokens: 600,
        messages: [{ role: 'user', content: prompt }],
    });

    const raw = message.content[0].text.trim();
    // Strip markdown code blocks if present
    const jsonStr = raw.replace(/^```json?\n?/i, '').replace(/\n?```$/, '').trim();
    return JSON.parse(jsonStr);
}

/**
 * Beantwortet eine Chat-Nachricht im Kontext des IT-Supports.
 * @param {Array<{role: 'user'|'assistant', content: string}>} messages
 * @returns {string}
 */
async function chat(messages, userMode = false) {
    const knowledgeContext = getKnowledgeContext();
    const basePrompt = userMode ? USER_SYSTEM_PROMPT : BASE_SYSTEM_PROMPT;
    const systemPrompt = knowledgeContext
        ? `${basePrompt}\n\n## Wissensdatenbank (bekannte Probleme & Lösungen)\n${knowledgeContext}`
        : basePrompt;

    const response = await getClient().messages.create({
        model: 'claude-sonnet-4-6',
        max_tokens: 1024,
        system: systemPrompt,
        messages,
    });

    return response.content[0].text;
}

/**
 * Lädt die Wissensdatenbank als Kontext-String.
 */
function getKnowledgeContext() {
    try {
        const db = getDatabase();
        const entries = db.prepare(
            'SELECT problem, solution, category FROM knowledge_base ORDER BY created_at DESC LIMIT 30'
        ).all();
        if (entries.length === 0) return '';
        return entries
            .map(e => `[${e.category}] Problem: ${e.problem}\nLösung: ${e.solution}`)
            .join('\n\n');
    } catch {
        return '';
    }
}

/**
 * Antwortet im Kontext eines konkreten Tickets.
 * @param {{ title, description, category, priority }} ticket
 * @param {Array<{role: 'user'|'assistant', content: string}>} messages
 * @returns {string}
 */
async function chatInTicket(ticket, messages) {
    const systemPrompt = `Du bist ein freundlicher IT-Hilfe-Assistent für Mitarbeiter der Cereda Systems GmbH.
Du hilfst einem Benutzer bei folgendem IT-Support-Ticket:

Titel: ${ticket.title}
Kategorie: ${ticket.category}
Priorität: ${ticket.priority}
Beschreibung: ${ticket.description || '(keine Beschreibung angegeben)'}

Antworte auf Deutsch in einfacher, verständlicher Sprache ohne Fachbegriffe.
Gib konkrete Schritt-für-Schritt-Anleitungen. Sei geduldig und freundlich.
Falls du das Problem nicht lösen kannst, weise den Benutzer freundlich darauf hin, dass ein Support-Mitarbeiter sich melden wird.`;

    const response = await getClient().messages.create({
        model: 'claude-sonnet-4-6',
        max_tokens: 1024,
        system: systemPrompt,
        messages,
    });

    return response.content[0].text;
}

/**
 * Prüft ob die AI-Integration konfiguriert ist.
 */
function isConfigured() {
    return !!process.env.ANTHROPIC_API_KEY;
}

/**
 * Generates a KB article from a closed ticket.
 * Returns null if the ticket has insufficient information.
 */
async function generateKbArticleFromTicket(ticketId) {
    const db = getDatabase();

    // Don't create duplicates
    const existing = db.prepare('SELECT id FROM knowledge_base WHERE source_ticket_id = ?').get(ticketId);
    if (existing) return null;

    const ticket = db.prepare('SELECT * FROM tickets WHERE id = ?').get(ticketId);
    if (!ticket) return null;

    const comments = db.prepare(`
        SELECT tc.content, tc.is_internal,
               COALESCE(u.first_name || ' ' || u.last_name, u.username, 'System') AS author
        FROM ticket_comments tc
        LEFT JOIN users u ON tc.user_id = u.id
        WHERE tc.ticket_id = ? AND tc.is_internal = 0
        ORDER BY tc.created_at ASC
    `).all(ticketId);

    const commentText = comments.length > 0
        ? comments.map(c => `[${c.author}]: ${c.content}`).join('\n')
        : '';

    const prompt = `Analysiere dieses abgeschlossene IT-Support-Ticket und erstelle daraus einen Wissensdatenbank-Artikel.
Antworte NUR mit einem validen JSON-Objekt. Wenn das Ticket zu wenig Inhalt hat um einen nützlichen Artikel zu erstellen, setze "worth_adding" auf false.

{
  "worth_adding": true,
  "problem": "<Kurze, prägnante Problembeschreibung (max 120 Zeichen)>",
  "solution": "<Detaillierte Schritt-für-Schritt-Lösung>",
  "category": "<Software|Hardware|Netzwerk|SelectLine|Allgemein|Sonstiges>",
  "tags": "<kommagetrennte Schlagwörter, max 5>"
}

Ticket-Titel: ${ticket.title}
Kategorie: ${ticket.category || 'Unbekannt'}
Beschreibung: ${ticket.description || '(keine Beschreibung)'}
${commentText ? `\nKommentare:\n${commentText}` : ''}`;

    try {
        const message = await getClient().messages.create({
            model: 'claude-sonnet-4-6',
            max_tokens: 800,
            messages: [{ role: 'user', content: prompt }],
        });

        const raw = message.content[0].text.trim().replace(/^```json?\n?/i, '').replace(/\n?```$/, '').trim();
        const result = JSON.parse(raw);

        if (!result.worth_adding) return null;

        const inserted = db.prepare(`
            INSERT INTO knowledge_base (problem, solution, category, tags, source_ticket_id, auto_generated, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
        `).run(result.problem, result.solution, result.category || 'Allgemein', result.tags || null, ticketId);

        console.log(`[KB] Auto-generated article #${inserted.lastInsertRowid} from ticket #${ticketId}`);
        return inserted.lastInsertRowid;
    } catch (err) {
        console.error(`[KB] Failed to generate article from ticket #${ticketId}:`, err.message);
        return null;
    }
}

/**
 * Imports free text/document content and generates one or more KB articles.
 * Returns array of created article IDs.
 */
async function importTextToKb(text, createdByUserId) {
    const prompt = `Analysiere den folgenden Text und erstelle daraus Wissensdatenbank-Artikel für eine IT-Abteilung.
Erstelle sowohl Problem/Lösungs-Paare ALS AUCH Informations-Artikel aus Dokumentation und Beschreibungen.
Bei Dokumentation: "problem" = "Was ist [Thema]? / Wie funktioniert [Thema]?" und "solution" = die Erklärung/Beschreibung.
Bei Anleitungen: "problem" = die Aufgabe/Frage und "solution" = die Schritt-für-Schritt-Anleitung.
Erstelle für jedes eigenständige Thema/Feature/Funktion einen separaten Artikel.
Antworte NUR mit einem validen JSON-Array:

[
  {
    "problem": "<Kurze Frage oder Problembeschreibung (max 120 Zeichen)>",
    "solution": "<Detaillierte Erklärung, Lösung oder Beschreibung>",
    "category": "<Software|Hardware|Netzwerk|SelectLine|Allgemein|Sonstiges>",
    "tags": "<kommagetrennte Schlagwörter>"
  }
]

Text:
${text.slice(0, 8000)}`;

    const message = await getClient().messages.create({
        model: 'claude-sonnet-4-6',
        max_tokens: 4096,
        messages: [{ role: 'user', content: prompt }],
    });

    const raw = message.content[0].text.trim().replace(/^```json?\n?/i, '').replace(/\n?```$/, '').trim();
    let articles;
    try { articles = JSON.parse(raw); } catch { articles = []; }
    if (!Array.isArray(articles)) articles = [];

    const db = getDatabase();
    const ids = [];
    for (const a of articles) {
        if (!a.problem?.trim() || !a.solution?.trim()) continue;
        const r = db.prepare(`
            INSERT INTO knowledge_base (problem, solution, category, tags, created_by_user_id, auto_generated, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
        `).run(a.problem.trim(), a.solution.trim(), a.category || 'Allgemein', a.tags || null, createdByUserId);
        ids.push(r.lastInsertRowid);
    }
    return ids;
}

/**
 * Analysiert einen NetGo-Monitoring-Alert mit Claude.
 * Extrahiert saubere Felder UND liefert eine Analyse.
 * @returns {{ device: string, service: string, state_from: string, state_to: string, severity: string, metrics: string, what: string, action_needed: boolean, recommendation: string }}
 */
async function analyzeNetgoAlert(alert) {
    const rawBody = alert.raw_body || '';
    const prompt = `Du bist ein erfahrener IT-Administrator bei Cereda Systems GmbH.
Analysiere diesen NetGo-Monitoring-Alert (Rohdaten aus E-Mail) und antworte NUR mit einem validen JSON-Objekt.

Rohdaten:
${rawBody.substring(0, 2000)}

Extrahiere und analysiere folgende Felder. Antworte NUR mit diesem JSON:
{
  "device": "<Gerätename, z.B. 'SERVER-SWYX01' – nur Hostname, kein Zusatztext>",
  "service": "<Service-Name, z.B. 'Disk Check C:' – kurz und präzise>",
  "state_from": "<Ausgangszustand, z.B. 'Warning' oder 'Normal'>",
  "state_to": "<Zielzustand, z.B. 'Failed' oder 'Normal'>",
  "severity": "<CRIT|WARN|OK – basierend auf dem Zielzustand>",
  "metrics": "<Relevante Messwerte in einer Zeile, z.B. 'Frei: 9,99 GB (10,06%) | Gesamt: 99,33 GB' oder leer wenn keine>",
  "what": "<Was bedeutet dieser Alert? 1-2 klare Sätze auf Deutsch ohne technischen Kauderwelsch>",
  "action_needed": <true wenn Handlungsbedarf, false bei Entwarnung/Recovery>,
  "recommendation": "<Was soll der IT-Admin jetzt konkret tun? 1-2 Sätze>"
}

Regeln:
- device: nur der reine Hostname/Gerätename
- severity OK = Entwarnung/Recovery, action_needed = false
- severity CRIT/WARN = Problem, action_needed = true
- Antworte immer auf Deutsch`;

    try {
        const message = await getClient().messages.create({
            model: 'claude-sonnet-4-6',
            max_tokens: 500,
            messages: [{ role: 'user', content: prompt }],
        });
        const raw = message.content[0].text.trim()
            .replace(/^```json?\n?/i, '').replace(/\n?```$/, '').trim();
        return JSON.parse(raw);
    } catch (err) {
        console.error('[AI] analyzeNetgoAlert failed:', err.message);
        return null;
    }
}

/**
 * Analysiert einen Microsoft Defender for Office 365 Alert mit Claude.
 * @param {object} alert - Gespeichertes ExternalAlert-Objekt (raw_body = vollständiger Graph-API-Response)
 * @returns {{ affected_user, threat_type, attack_vector, what, action_needed, recommendation }}
 */
async function analyzeMdoAlert(alert) {
    let raw = {};
    try { raw = typeof alert.raw_body === 'string' ? JSON.parse(alert.raw_body) : (alert.raw_body || {}); } catch {}

    const prompt = `Du bist ein erfahrener IT-Sicherheitsadministrator bei Cereda Systems GmbH.
Analysiere diesen Microsoft Defender for Office 365 Security Alert und antworte NUR mit einem validen JSON-Objekt auf Deutsch.

Alert-Daten:
Titel: ${raw.title || alert.message || '(unbekannt)'}
Kategorie: ${raw.category || ''}
Schweregrad: ${raw.severity || alert.severity || ''}
Status: ${raw.status || alert.state_transition || ''}
Betroffener Nutzer: ${alert.device || ''}
Erstellt: ${raw.createdDateTime || alert.state_time || ''}
Bedrohungsfamilie: ${raw.threatFamilyName || ''}
Beschreibung: ${(raw.description || '').substring(0, 800)}
Empfehlung (Microsoft): ${(Array.isArray(raw.recommendedActions) ? raw.recommendedActions.join('; ') : (raw.recommendedActions || '')).substring(0, 400)}
Evidence: ${JSON.stringify((raw.evidence || []).slice(0, 3)).substring(0, 600)}

Antworte NUR mit diesem JSON-Objekt:
{
  "affected_user": "<E-Mail-Adresse des betroffenen Benutzers>",
  "threat_type": "<Art der Bedrohung, z.B. 'Phishing', 'Malware', 'BEC', 'Spam'>",
  "attack_vector": "<Angriffsvektor, z.B. 'E-Mail', 'Link', 'Anhang'>",
  "what": "<Was ist passiert? 2-3 klare Sätze auf Deutsch>",
  "action_needed": <true wenn sofortiger Handlungsbedarf, sonst false>,
  "recommendation": "<Was soll der IT-Admin jetzt konkret tun? 1-3 Sätze auf Deutsch>"
}`;

    try {
        const message = await getClient().messages.create({
            model: 'claude-sonnet-4-6',
            max_tokens: 600,
            messages: [{ role: 'user', content: prompt }],
        });
        const raw2 = message.content[0].text.trim()
            .replace(/^```json?\n?/i, '').replace(/\n?```$/, '').trim();
        return JSON.parse(raw2);
    } catch (err) {
        console.error('[AI] analyzeMdoAlert failed:', err.message);
        return null;
    }
}

module.exports = { analyzeTicket, chat, chatInTicket, getKnowledgeContext, isConfigured, generateKbArticleFromTicket, importTextToKb, analyzeNetgoAlert, analyzeMdoAlert };
