/**
 * Compliance Advisor Chat API
 *
 * Connects the ComplianceAdvisorWidget to:
 * 1. Multi-Collection RAG search (rag-service) for context across 6 collections
 * 2. Ollama LLM (32B) for generating answers
 *
 * Supports country-specific filtering (DE, AT, CH, EU).
 * Streams the LLM response back as plain text.
 */

import { NextRequest, NextResponse } from 'next/server'
import { readSoulFile } from '@/lib/sdk/agents/soul-reader'

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

// All compliance-relevant collections (without NiBiS)
const COMPLIANCE_COLLECTIONS = [
  'bp_compliance_gesetze',
  'bp_compliance_ce',
  'bp_compliance_datenschutz',
  'bp_dsfa_corpus',
  'bp_compliance_recht',
  'bp_legal_templates',
] as const

type Country = 'DE' | 'AT' | 'CH' | 'EU'

// Fallback SOUL prompt (used when .soul.md file is unavailable)
const FALLBACK_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.

## Kernprinzipien
- Quellenbasiert: Verweise auf DSGVO-Artikel, BDSG-Paragraphen
- Verstaendlich: Einfache, praxisnahe Sprache
- Ehrlich: Bei Unsicherheit empfehle Rechtsberatung
- Deutsch als Hauptsprache`

const COUNTRY_LABELS: Record<Country, string> = {
  DE: 'Deutschland',
  AT: 'Oesterreich',
  CH: 'Schweiz',
  EU: 'EU-weit',
}

interface RAGSearchResult {
  content: string
  source_name?: string
  source_code?: string
  attribution_text?: string
  score: number
  collection?: string
  metadata?: Record<string, unknown>
}

/**
 * Query multiple RAG collections in parallel, with optional country filter
 */
async function queryMultiCollectionRAG(query: string, country?: Country): Promise<string> {
  try {
    const searchPromises = COMPLIANCE_COLLECTIONS.map(async (collection) => {
      const searchBody: Record<string, unknown> = {
        query,
        collection,
        top_k: 3,
      }

      // Apply country filter for gesetze collection
      if (collection === 'bp_compliance_gesetze' && country && country !== 'EU') {
        searchBody.metadata_filter = {
          must: [
            {
              key: 'country',
              match: { any: [country, 'EU'] },
            },
          ],
        }
      }

      const res = await fetch(`${RAG_SERVICE_URL}/api/v1/search`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(searchBody),
        signal: AbortSignal.timeout(10000),
      })

      if (!res.ok) return []

      const data = await res.json()
      return (data.results || []).map((r: RAGSearchResult) => ({
        ...r,
        collection,
      }))
    })

    const settled = await Promise.allSettled(searchPromises)
    const allResults: RAGSearchResult[] = []

    for (const result of settled) {
      if (result.status === 'fulfilled') {
        allResults.push(...result.value)
      }
    }

    // Sort by score descending, take top 8
    allResults.sort((a, b) => b.score - a.score)
    const topResults = allResults.slice(0, 8)

    if (topResults.length === 0) return ''

    return topResults
      .map((r, i) => {
        const source = r.source_name || r.source_code || 'Unbekannt'
        return `[Quelle ${i + 1}: ${source}]\n${r.content || ''}`
      })
      .join('\n\n---\n\n')
  } catch (error) {
    console.warn('Multi-collection 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', country } = body

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

    // Validate country parameter
    const validCountry = ['DE', 'AT', 'CH', 'EU'].includes(country) ? (country as Country) : undefined

    // 1. Query RAG across all collections
    const ragContext = await queryMultiCollectionRAG(message, validCountry)

    // 2. Build system prompt with RAG context + country
    const soulPrompt = await readSoulFile('compliance-advisor')
    let systemContent = soulPrompt || FALLBACK_SYSTEM_PROMPT

    if (validCountry) {
      const countryLabel = COUNTRY_LABELS[validCountry]
      systemContent += `\n\n## Laenderspezifische Auskunft
Der Nutzer hat "${countryLabel} (${validCountry})" gewaehlt.
- Beziehe dich AUSSCHLIESSLICH auf ${validCountry}-Recht + anwendbares EU-Recht
- Nenne IMMER explizit das Land in deiner Antwort
- Verwende NIEMALS Gesetze eines anderen Landes
- Bei ${validCountry === 'EU' ? 'EU-weiten Fragen: Beziehe dich auf EU-Verordnungen und -Richtlinien' : `${countryLabel}: Beziehe nationale Gesetze (${validCountry === 'DE' ? 'BDSG, TDDDG, TKG, UWG' : validCountry === 'AT' ? 'AT DSG, ECG, TKG, KSchG, MedienG' : 'CH DSG, DSV, OR, UWG, FMG'}) mit ein`}`
    }

    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 6 messages)
    const messages = [
      { role: 'system', content: systemContent },
      ...history.slice(-6).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,
        think: false,
        options: {
          temperature: 0.3,
          num_predict: 8192,
          num_ctx: 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 }
    )
  }
}
