/**
 * Compliance Advisor Chat API
 *
 * Connects the ComplianceAdvisorWidget to:
 * 1. RAG legal corpus search (klausur-service) for context
 * 2. Ollama LLM (32B) for generating answers
 *
 * Streams the LLM response back as plain text.
 */

import { NextRequest, NextResponse } from 'next/server'

const KLAUSUR_SERVICE_URL = process.env.KLAUSUR_SERVICE_URL || 'http://klausur-service:8086'
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://host.docker.internal:11434'
const LLM_MODEL = process.env.COMPLIANCE_LLM_MODEL || 'qwen2.5vl:32b'

// SOUL system prompt (from agent-core/soul/compliance-advisor.soul.md)
const SYSTEM_PROMPT = `# Compliance Advisor Agent

## Identitaet
Du bist der BreakPilot Compliance-Berater. Du hilfst Nutzern des AI Compliance SDK,
Datenschutz- und Compliance-Fragen in verstaendlicher Sprache zu beantworten.
Du bist kein Anwalt und gibst keine Rechtsberatung, sondern orientierst dich an
offiziellen Quellen und gibst praxisnahe Hinweise.

## Kernprinzipien
- **Quellenbasiert**: Verweise immer auf konkrete Rechtsgrundlagen (DSGVO-Artikel, BDSG-Paragraphen)
- **Verstaendlich**: Erklaere rechtliche Konzepte in einfacher, praxisnaher Sprache
- **Ehrlich**: Bei Unsicherheit empfehle professionelle Rechtsberatung
- **Kontextbewusst**: Nutze das RAG-System fuer aktuelle Rechtstexte und Leitfaeden
- **Scope-bewusst**: Nutze alle verfuegbaren RAG-Quellen (DSGVO, BDSG, AI Act, TTDSG, DSK-Kurzpapiere, SDM, BSI, Laender-Muss-Listen, EDPB Guidelines, etc.) AUSSER NIBIS-Dokumenten.

## Kompetenzbereich
- DSGVO Art. 1-99 + Erwaegsgruende
- BDSG (Bundesdatenschutzgesetz)
- AI Act (EU KI-Verordnung)
- TTDSG (Telekommunikation-Telemedien-Datenschutz-Gesetz)
- ePrivacy-Richtlinie
- DSK-Kurzpapiere (Nr. 1-20)
- SDM (Standard-Datenschutzmodell) V3.0
- BSI-Grundschutz (Basis-Kenntnisse)
- BSI-TR-03161 (Sicherheitsanforderungen an digitale Gesundheitsanwendungen)
- ISO 27001/27701 (Ueberblick)
- EDPB Guidelines (Leitlinien des Europaeischen Datenschutzausschusses)
- Bundes- und Laender-Muss-Listen (DSFA-Listen der Aufsichtsbehoerden)
- WP29/WP248 (Art.-29-Datenschutzgruppe Arbeitspapiere)

## RAG-Nutzung
Nutze das gesamte RAG-Corpus fuer Kontext und Quellenangaben — ausgenommen sind
NIBIS-Inhalte (Erwartungshorizonte, Bildungsstandards, curriculare Vorgaben).
Diese gehoeren nicht zum Datenschutz-Kompetenzbereich.

## Kommunikationsstil
- Sachlich, aber verstaendlich — kein Juristendeutsch
- Deutsch als Hauptsprache
- Strukturierte Antworten mit Ueberschriften und Aufzaehlungen
- Immer Quellenangabe (Artikel/Paragraph) am Ende der Antwort
- Praxisbeispiele wo hilfreich
- Kurze, praegnante Saetze

## Antwortformat
1. Kurze Zusammenfassung (1-2 Saetze)
2. Detaillierte Erklaerung
3. Praxishinweise / Handlungsempfehlungen
4. Quellenangaben (Artikel, Paragraph, Leitlinie)

## Einschraenkungen
- Gib NIEMALS konkrete Rechtsberatung ("Sie muessen..." -> "Es empfiehlt sich...")
- Keine Garantien fuer Rechtssicherheit
- Bei komplexen Einzelfaellen: Empfehle Rechtsanwalt/DSB
- Keine Aussagen zu laufenden Verfahren oder Bussgeldern
- Keine Interpretation von Urteilen (nur Verweis)

## Eskalation
- Bei Fragen ausserhalb des Kompetenzbereichs: Hoeflich ablehnen und auf Fachanwalt verweisen
- Bei widerspruechlichen Rechtslagen: Beide Positionen darstellen und DSB-Konsultation empfehlen
- Bei dringenden Datenpannen: Auf 72-Stunden-Frist (Art. 33 DSGVO) hinweisen und Notfallplan-Modul empfehlen`

interface RAGResult {
  content: string
  source_name: string
  source_code: string
  attribution_text: string
  score: number
}

/**
 * Query the DSFA RAG corpus for relevant documents
 */
async function queryRAG(query: string): Promise<string> {
  try {
    const url = `${KLAUSUR_SERVICE_URL}/api/v1/dsfa-rag/search?query=${encodeURIComponent(query)}&top_k=5`
    const res = await fetch(url, {
      headers: { 'Content-Type': 'application/json' },
      signal: AbortSignal.timeout(10000),
    })

    if (!res.ok) {
      console.warn('RAG search failed:', res.status)
      return ''
    }

    const data = await res.json()

    if (data.results && data.results.length > 0) {
      return data.results
        .map(
          (r: RAGResult, i: number) =>
            `[Quelle ${i + 1}: ${r.source_name || r.source_code || 'Unbekannt'}]\n${r.content || ''}`
        )
        .join('\n\n---\n\n')
    }

    return ''
  } catch (error) {
    console.warn('RAG query error (continuing without context):', error)
    return ''
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const { message, history = [], currentStep = 'default' } = body

    if (!message || typeof message !== 'string') {
      return NextResponse.json({ error: 'Message is required' }, { status: 400 })
    }

    // 1. Query RAG for relevant context
    const ragContext = await queryRAG(message)

    // 2. Build system prompt with RAG context
    let systemContent = SYSTEM_PROMPT

    if (ragContext) {
      systemContent += `\n\n## Relevanter Kontext aus dem RAG-System\n\nNutze die folgenden Quellen fuer deine Antwort. Verweise in deiner Antwort auf die jeweilige Quelle:\n\n${ragContext}`
    }

    systemContent += `\n\n## Aktueller SDK-Schritt\nDer Nutzer befindet sich im SDK-Schritt: ${currentStep}`

    // 3. Build messages array (limit history to last 10 messages)
    const messages = [
      { role: 'system', content: systemContent },
      ...history.slice(-10).map((h: { role: string; content: string }) => ({
        role: h.role === 'user' ? 'user' : 'assistant',
        content: h.content,
      })),
      { role: 'user', content: message },
    ]

    // 4. Call Ollama with streaming
    const ollamaResponse = await fetch(`${OLLAMA_URL}/api/chat`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        model: LLM_MODEL,
        messages,
        stream: true,
        options: {
          temperature: 0.3,
          num_predict: 8192,
        },
      }),
      signal: AbortSignal.timeout(120000),
    })

    if (!ollamaResponse.ok) {
      const errorText = await ollamaResponse.text()
      console.error('Ollama error:', ollamaResponse.status, errorText)
      return NextResponse.json(
        { error: `LLM nicht erreichbar (Status ${ollamaResponse.status}). Ist Ollama mit dem Modell ${LLM_MODEL} gestartet?` },
        { status: 502 }
      )
    }

    // 5. Stream response back as plain text
    const encoder = new TextEncoder()
    const stream = new ReadableStream({
      async start(controller) {
        const reader = ollamaResponse.body!.getReader()
        const decoder = new TextDecoder()

        try {
          while (true) {
            const { done, value } = await reader.read()
            if (done) break

            const chunk = decoder.decode(value, { stream: true })
            const lines = chunk.split('\n').filter((l) => l.trim())

            for (const line of lines) {
              try {
                const json = JSON.parse(line)
                if (json.message?.content) {
                  controller.enqueue(encoder.encode(json.message.content))
                }
              } catch {
                // Partial JSON line, skip
              }
            }
          }
        } catch (error) {
          console.error('Stream read error:', error)
        } finally {
          controller.close()
        }
      },
    })

    return new NextResponse(stream, {
      headers: {
        'Content-Type': 'text/plain; charset=utf-8',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
      },
    })
  } catch (error) {
    console.error('Compliance advisor chat error:', error)
    return NextResponse.json(
      { error: 'Verbindung zum LLM fehlgeschlagen. Bitte pruefen Sie ob Ollama laeuft.' },
      { status: 503 }
    )
  }
}
