import { NextRequest, NextResponse } from 'next/server'
import pool from '@/lib/db'
import { getSessionFromCookie } from '@/lib/auth'
import { SLIDE_ORDER, SHOWCASE_HIDDEN_SLIDES } from '@/lib/slide-order'

const LITELLM_URL = process.env.LITELLM_URL || 'https://llm-dev.meghsakha.com'
const LITELLM_MODEL = process.env.LITELLM_MODEL || 'gpt-oss-120b'
const LITELLM_API_KEY = process.env.LITELLM_API_KEY || ''

// Build SLIDE_NAMES dynamically from SLIDE_ORDER
const SLIDE_DISPLAY_NAMES: Record<string, { de: string; en: string }> = {
  'intro-presenter': { de: 'Intro', en: 'Intro' },
  'cover': { de: 'Cover', en: 'Cover' },
  'problem': { de: 'Das Problem', en: 'The Problem' },
  'solution': { de: 'Die Lösung', en: 'The Solution' },
  'usp': { de: 'USP', en: 'USP' },
  'product': { de: 'Produkte', en: 'Products' },
  'how-it-works': { de: 'So funktioniert\'s', en: 'How It Works' },
  'market': { de: 'Markt', en: 'Market' },
  'business-model': { de: 'Geschäftsmodell', en: 'Business Model' },
  'traction': { de: 'Meilensteine', en: 'Milestones' },
  'competition': { de: 'Wettbewerb', en: 'Competition' },
  'team': { de: 'Team', en: 'Team' },
  'financials': { de: 'Finanzen', en: 'Financials' },
  'the-ask': { de: 'The Ask', en: 'The Ask' },
  'ai-qa': { de: 'KI Q&A', en: 'AI Q&A' },
  'annex-assumptions': { de: 'Anhang: Annahmen', en: 'Appendix: Assumptions' },
  'annex-architecture': { de: 'Anhang: Architektur', en: 'Appendix: Architecture' },
  'annex-gtm': { de: 'Anhang: Go-to-Market', en: 'Appendix: Go-to-Market' },
  'annex-regulatory': { de: 'Anhang: Regulatorik', en: 'Appendix: Regulatory' },
  'annex-engineering': { de: 'Anhang: Engineering', en: 'Appendix: Engineering' },
  'annex-aipipeline': { de: 'Anhang: KI-Pipeline', en: 'Appendix: AI Pipeline' },
  'annex-sdk-demo': { de: 'Anhang: SDK Demo', en: 'Appendix: SDK Demo' },
}

const slideCount = SLIDE_ORDER.length

// Static prefix: Identität through Kernbotschaft #8 — #9 and VERSIONS-ISOLATION injected at runtime
const SYSTEM_PROMPT_PART1 = `# Investor Agent — BreakPilot ComplAI

## Identität
Du bist der BreakPilot ComplAI Investor Relations Agent. Du beantwortest Fragen von
potenziellen Investoren über das Unternehmen, das Produkt, den Markt und die Finanzprognosen.
Du hast Zugriff auf alle Unternehmensdaten und zitierst immer konkrete Zahlen.

## Kernprinzipien
- **Datengetrieben**: Beziehe dich immer auf die bereitgestellten Unternehmensdaten
- **Präzise**: Nenne immer konkrete Zahlen, Prozentsätze und Zeiträume
- **Begeisternd aber ehrlich**: Stelle das Unternehmen positiv dar, ohne zu übertreiben
- **Zweisprachig**: Antworte in der Sprache, in der die Frage gestellt wird

## Kernbotschaften (IMMER betonen wenn passend)
1. Kern-Produkt: "BreakPilot COMPLAI — DSGVO-konforme KI-Plattform mit 12 Modulen. Kontinuierliche Code-Security und Compliance-Automatisierung. 380+ Gesetze und Regularien, 25.000+ Prüfaspekte."
2. Das Problem: "Unternehmen stehen vor einem strategischen Dilemma: Ohne KI verlieren sie Wettbewerbsfähigkeit. Mit US-KI riskieren sie Datenkontrollverlust. Über 30.000 Unternehmen in DE durch EU-Regulierungen belastet."
3. 12 Module: "Code Security (SAST/DAST/SBOM/Pentesting), CE-Software-Risikobeurteilung, Compliance-Dokumente (VVT/DSFA/TOMs), Audit Manager, DSR/Betroffenenrechte, Consent Management, Notfallpläne, Cookie-Generator, Compliance LLM, Academy, Integration in Kundenprozesse, Sichere Kommunikation."
4. Code & CE: "Kontinuierlich statt einmal im Jahr. CE-Software-Risikobeurteilung auf Code-Basis schon in der Entwicklung. Findings als Tickets mit Implementierungsvorschlägen."
5. EU-Infrastruktur: "BSI-zertifizierte Cloud in Deutschland oder Frankreich. 100% Datensouveränität. KEINE US-Anbieter. Isolierte Namespaces."
6. Zielgruppen: "Maschinen- und Anlagenbauer, Automobilindustrie, Zulieferer und alle produzierenden Unternehmen."
7. Geschäftsmodell: "SaaS, mitarbeiterbasiertes Pricing. Drei Tiers: Starter (3.600 EUR/Jahr), Professional (15.000-40.000 EUR/Jahr), Enterprise (ab 50.000 EUR/Jahr). Plus Beratung & Service (10.000-30.000 EUR/Monat). Kunden sparen mehr als sie zahlen — ROI ab Tag 1."
8. Team: "Lean-Team: 2 Gründer + 7 Mitarbeiter bis 2030 (9 Personen gesamt). Erste Einstellung: IT-Recht/Datenschutzjurist (50%). Dann: Security Engineer, Vertrieb, Backend, Kundenbetreuer, Marketing, DevOps. Jede Einstellung an konkreten Umsatzmeilenstein gekoppelt."`

// Static middle: Kommunikationsstil — injected between #9 and VERSIONS-ISOLATION
const SYSTEM_PROMPT_PART2 = `

## Kommunikationsstil
- Antworte IMMER wie ein Mensch in einem persönlichen Gespräch — ausformulierte Sätze, natürlicher Redefluss
- KEINE Bulletpoint-Listen. KEINE Aufzählungen mit Spiegelstrichen. Schreibe Fließtext in Absätzen.
- Erkläre das WARUM hinter jeder Aussage. Nicht nur "was" ihr tut, sondern begründe die Entscheidung.
- Nutze Übergangssätze wie "Der Grund dafür ist...", "Das haben wir bewusst so entschieden, weil...", "Besonders wichtig ist dabei..."
- Zahlen und Fakten natürlich in den Text einbetten, nicht als Liste aufreihen
- 3-5 Absätze pro Antwort, jeder Absatz ein eigenständiger Gedanke
- Der Text muss sich gut anhören wenn er vorgelesen wird (TTS-optimiert)`

// Static suffix: everything after VERSIONS-ISOLATION
const SYSTEM_PROMPT_PART3 = `

## IP-Schutz-Layer (KRITISCH)
NIEMALS offenbaren: Exakte Modellnamen, Frameworks, Code-Architektur, Datenbankschema, Sicherheitsdetails, Cloud-Provider.
Stattdessen: "Proprietäre KI-Engine", "BSI-zertifizierte EU-Cloud (SysEleven, Hetzner)", "Isolierte Kunden-Namespaces", "Enterprise-Grade Verschlüsselung".

## Erlaubt: Geschäftsmodell, Preise, Marktdaten, Features, Team, Finanzen, Use of Funds, Hardware-Specs (öffentlich), LLM-Größen (32b/40b/1000b), CE-Risikobeurteilung, Issue-Tracker-Integration, Meeting-Recorder, Matrix/Jitsi.

## Team-Antworten (WICHTIG)
Wenn nach dem Team gefragt wird: IMMER die Namen, Rollen und Expertise der Gründer aus den bereitgestellten Daten nennen. NIEMALS vage Antworten wie "unser Team vereint Expertise" ohne Namen. Zitiere die konkreten Personen aus den Unternehmensdaten.

## Slide-Awareness (IMMER beachten)
Du erhältst den aktuellen Slide-Kontext. Nutze ihn für kontextuelle Antworten.
Wenn der Investor etwas fragt, was in einer späteren Slide detailliert wird und er diese noch nicht gesehen hat:
- Beantworte kurz, dann: "Details dazu finden Sie in Slide X: [Name]. Möchten Sie dorthin springen? [GOTO:slide-id]"
- Verwende [GOTO:slide-id] mit der Slide-ID (z.B. [GOTO:financials], [GOTO:competition])

## FOLLOW-UP FRAGEN — KRITISCHE PFLICHT

Du MUSST am Ende JEDER einzelnen Antwort exakt 3 Folgefragen anhängen.
Die Fragen müssen durch "---" getrennt und mit "[Q]" markiert sein.
JEDE Antwort ohne Folgefragen ist UNVOLLSTÄNDIG und FEHLERHAFT.

EXAKTES FORMAT (keine Abweichung erlaubt):

[Deine Antwort hier]

---
[Q] Erste Folgefrage passend zum Thema?
[Q] Zweite Folgefrage die tiefer geht?
[Q] Dritte Folgefrage zu einem verwandten Aspekt?

KONKRETES BEISPIEL einer vollständigen Antwort:

"Unser AI-First-Ansatz ermöglicht Skalierung ohne lineares Personalwachstum. Der Umsatz steigt planmäßig über die Jahre stark an, während das Team lean bleibt.

---
[Q] Wie sieht die Kostenstruktur im Detail aus?
[Q] Welche Unit Economics erreicht ihr in 2030?
[Q] Wie vergleicht sich die Personaleffizienz mit Wettbewerbern?"

WICHTIG: Vergiss NIEMALS die Folgefragen! Sie sind PFLICHT.`

// Prepended to system content for showcase (customer demo) sessions
const SHOWCASE_GUARD = `## MODUS: PRODUKT-DEMO (KEIN INVESTOREN-PITCH)
Du bist im Showcase-Modus. Du beantwortest Fragen potenzieller Kunden über das Produkt — NICHT über Investitionsdetails.

ABSOLUTES VERBOT — niemals erwähnen oder beantworten:
- Finanzierungssumme, Investitionsbedarf, The Ask, Bewertung, Equity, Cap Table
- Finanzprognosen, Umsatzziele, Cashflow, Liquidität, Burn Rate
- Wandeldarlehen, SAFE, Gesellschafteranteile oder Kapitalstruktur
- Irgendwelche Zahlen aus dem Finanzplan oder Finanzierungsrunden

Wenn danach gefragt wird: "Für geschäftliche Details wenden Sie sich gerne direkt an unser Team."
Fokus: Produkt-Features, Compliance-Module, technische Architektur, Kundennutzen, Markt, Team.`

async function loadFpLiquiditaetSummary(scenarioName: string): Promise<string> {
  try {
    const { rows } = await pool.query(
      `SELECT l.row_label, l.values
       FROM fp_liquiditaet l
       JOIN fp_scenarios s ON s.id = l.scenario_id
       WHERE s.name = $1
         AND l.row_label IN ('LIQUIDITÄT', 'LIQUIDITAET', 'Summe ERTRÄGE', 'Summe EINZAHLUNGEN', 'Summe AUSZAHLUNGEN', 'ÜBERSCHUSS')
       ORDER BY l.sort_order`,
      [scenarioName]
    )
    if (rows.length === 0) {
      if (scenarioName) console.warn('[chat] loadFpLiquiditaetSummary: no rows for scenario', JSON.stringify(scenarioName))
      return ''
    }

    const years = [2026, 2027, 2028, 2029, 2030]
    const summary: Record<string, Record<number, number>> = {}
    for (const row of rows) {
      const label = row.row_label === 'LIQUIDITAET' ? 'LIQUIDITÄT' : row.row_label
      summary[label] = {}
      for (let yi = 0; yi < years.length; yi++) {
        const start = yi * 12 + 1
        const end = start + 11
        // LIQUIDITÄT is a balance (end-of-period): use December value
        if (label === 'LIQUIDITÄT') {
          summary[label][years[yi]] = Math.round(row.values[`m${end}`] || 0)
        } else {
          let s = 0
          for (let m = start; m <= end; m++) s += row.values[`m${m}`] || 0
          summary[label][years[yi]] = Math.round(s)
        }
      }
    }

    const lines = [`### Finanzplan-Liquidität (Szenario: ${scenarioName})`]
    for (const [label, yearVals] of Object.entries(summary)) {
      const vals = years.map(y => `${y}: ${(yearVals[y] || 0).toLocaleString('de-DE')} EUR`).join(' | ')
      lines.push(`${label}: ${vals}`)
    }
    return lines.join('\n')
  } catch {
    return ''
  }
}

interface VersionMeta {
  versionName: string
  scenarioName: string
  fundingAmount: number
  fundingInstrument: string
  customers2030: number
  revenue2030: number
  employees2030: number
}

interface PitchContextResult {
  contextString: string
  meta: VersionMeta
}

const DEFAULT_META: VersionMeta = {
  versionName: '', scenarioName: '', fundingAmount: 0,
  fundingInstrument: 'Wandeldarlehen', customers2030: 0, revenue2030: 0, employees2030: 0,
}

function extractMeta(
  versionName: string,
  fmScenarios: Array<{ name: string }> | undefined,
  funding: Record<string, unknown> | null,
  financials: Array<Record<string, unknown>>
): VersionMeta {
  const fin2030 = financials.find(f => Number(f.year) === 2030) ?? {}
  return {
    versionName,
    scenarioName: fmScenarios?.[0]?.name ?? versionName,
    fundingAmount: Number(funding?.amount_eur ?? 0),
    fundingInstrument: String(funding?.instrument ?? 'Wandeldarlehen'),
    customers2030: Number(fin2030.customers_count ?? 0),
    revenue2030: Number(fin2030.revenue_eur ?? 0),
    employees2030: Number(fin2030.employees_count ?? 0),
  }
}

async function loadPitchContext(versionId?: string | null, isShowcase = false): Promise<PitchContextResult> {
  try {
    // Version-specific data path
    if (versionId) {
      const [vDataRes, vNameRes] = await Promise.all([
        pool.query(`SELECT table_name, data FROM pitch_version_data WHERE version_id = $1`, [versionId]),
        pool.query(`SELECT name FROM pitch_versions WHERE id = $1`, [versionId]),
      ])

      const map: Record<string, unknown> = {}
      for (const r of vDataRes.rows) {
        map[r.table_name] = typeof r.data === 'string' ? JSON.parse(r.data) : r.data
      }

      const company = (map.company as unknown[])?.[0] ?? null
      const team = (map.team as unknown[]) ?? []
      const financials = (map.financials as Array<Record<string, unknown>>) ?? []
      const market = (map.market as unknown[]) ?? []
      const products = (map.products as unknown[]) ?? []
      const funding = ((map.funding as unknown[])?.[0] as Record<string, unknown>) ?? null
      const features = ((map.features as Array<Record<string, unknown>>) ?? [])
        .filter(f => f.is_differentiator)
      const fmScenarios = map.fm_scenarios as Array<{ name: string }> | undefined

      const versionName = vNameRes.rows[0]?.name ?? ''
      const meta = extractMeta(versionName, fmScenarios, funding, financials)
      const fpSummary = (!isShowcase && meta.scenarioName) ? await loadFpLiquiditaetSummary(meta.scenarioName) : ''

      return {
        contextString: buildContextString(company, team, financials, market, products, funding, features, fpSummary, isShowcase),
        meta: isShowcase ? { ...DEFAULT_META, versionName } : meta,
      }
    }

    // Fallback: base tables
    const client = await pool.connect()
    try {
      const [company, team, financials, market, products, funding, features] = await Promise.all([
        client.query('SELECT * FROM pitch_company LIMIT 1'),
        client.query('SELECT name, role_de, equity_pct, expertise FROM pitch_team ORDER BY sort_order'),
        client.query('SELECT year, revenue_eur, costs_eur, mrr_eur, customers_count, employees_count, arr_eur FROM pitch_financials ORDER BY year'),
        client.query('SELECT market_segment, value_eur, growth_rate_pct, source FROM pitch_market'),
        client.query('SELECT name, hardware, hardware_cost_eur, monthly_price_eur, llm_size, llm_capability_de, operating_cost_eur FROM pitch_products ORDER BY sort_order'),
        client.query('SELECT round_name, amount_eur, use_of_funds, instrument FROM pitch_funding LIMIT 1'),
        client.query('SELECT feature_name_de, breakpilot, proliance, dataguard, heydata, is_differentiator FROM pitch_features WHERE is_differentiator = true'),
      ])
      const meta = extractMeta('', undefined, funding.rows[0] ?? null, financials.rows)
      return {
        contextString: buildContextString(
          company.rows[0], team.rows, financials.rows, market.rows,
          products.rows, funding.rows[0], features.rows, '', isShowcase
        ),
        meta: isShowcase ? DEFAULT_META : meta,
      }
    } finally {
      client.release()
    }
  } catch (error) {
    console.warn('Could not load pitch context from DB:', error)
    return { contextString: '', meta: DEFAULT_META }
  }
}

function buildContextString(
  company: unknown, team: unknown, financials: unknown, market: unknown,
  products: unknown, funding: unknown, features: unknown, fpSummary: string,
  omitFinancials = false
): string {
  const finSection = omitFinancials ? '' : `
### Finanzprognosen (5-Jahres-Plan)
${JSON.stringify(financials, null, 2)}
`
  const fundSection = omitFinancials ? '' : `
### Finanzierung
${JSON.stringify(funding, null, 2)}
`
  const fpSection = omitFinancials ? '' : (fpSummary ? '\n' + fpSummary : '')

  return `
## Unternehmensdaten (für präzise Antworten nutzen)

### Firma
${JSON.stringify(company, null, 2)}

### Team
${JSON.stringify(team, null, 2)}
${finSection}
### Markt (TAM/SAM/SOM)
${JSON.stringify(market, null, 2)}

### Produkte
${JSON.stringify(products, null, 2)}
${fundSection}
### Differenzierende Features (nur bei ComplAI)
${JSON.stringify(features, null, 2)}
${fpSection}
`
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const { message, history = [], lang: langParam = 'de', slideContext, faqContext } = body
    const lang: 'de' | 'en' = langParam === 'en' ? 'en' : 'de'

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

    // Resolve investor's assigned version and showcase flag
    let versionId: string | null = null
    let isShowcase = false
    try {
      const session = await getSessionFromCookie()
      if (session?.sub) {
        const inv = await pool.query(
          `SELECT assigned_version_id, is_showcase FROM pitch_investors WHERE id = $1`,
          [session.sub]
        )
        versionId = inv.rows[0]?.assigned_version_id ?? null
        isShowcase = inv.rows[0]?.is_showcase === true
      }
    } catch {
      // Non-fatal: fall back to base tables
    }

    const { contextString, meta } = await loadPitchContext(versionId, isShowcase)

    // Build dynamic VERSIONS-ISOLATION and Kernbotschaft #9 from actual version data
    const fmt = (n: number) => n.toLocaleString('de-DE')
    const revM = meta.revenue2030 > 0
      ? `~${(meta.revenue2030 / 1_000_000).toFixed(1).replace('.', ',')} Mio. EUR`
      : 'laut Finanzplan'
    const fundingStr = meta.fundingAmount > 0
      ? `${fmt(meta.fundingAmount)} EUR ${meta.fundingInstrument}`
      : meta.fundingInstrument
    const customersStr = meta.customers2030 > 0 ? `~${meta.customers2030} Kunden` : 'laut Finanzplan'
    const employeesStr = meta.employees2030 > 0 ? `${meta.employees2030} Mitarbeiter` : 'laut Finanzplan'

    const dynamicVersionIsolation = `## VERSIONS-ISOLATION (ABSOLUT KRITISCH)
- Es gibt NUR dieses eine Pitch Deck. Es wurde individuell für diesen Investor erstellt.
- Wenn gefragt wird ob es andere Versionen, andere Pitch Decks oder andere Konditionen gibt: "Dieses Pitch Deck wurde persönlich für Sie erstellt. Es gibt genau dieses."
- NIEMALS Begriffe wie "Version", "Szenario", "Variante" oder "diese Version" verwenden — das impliziert, es könnte andere geben.
- NIEMALS erwähnen: andere Finanzierungssummen, andere Bewertungen, andere Cap Tables, andere Szenarien.
- Alle Zahlen beziehen sich auf: ${fundingStr}, ${customersStr} bis 2030, ${revM} Umsatz, ${employeesStr}.`

    const dynamicFinanzplanKernbotschaft = `9. Finanzplan: "Gründung August 2026. Pre-Seed über ${fundingStr}. ${customersStr} und ${revM} Umsatz bis 2030. ${employeesStr}."`

    let systemContent: string
    if (isShowcase) {
      // Showcase: product-only context, no financial details anywhere
      systemContent = SHOWCASE_GUARD
        + '\n\n' + SYSTEM_PROMPT_PART1
        + SYSTEM_PROMPT_PART2
        + SYSTEM_PROMPT_PART3
    } else {
      systemContent = SYSTEM_PROMPT_PART1
        + '\n' + dynamicFinanzplanKernbotschaft
        + SYSTEM_PROMPT_PART2
        + '\n\n' + dynamicVersionIsolation
        + SYSTEM_PROMPT_PART3
    }

    if (contextString) {
      systemContent += '\n' + contextString
    }

    // FAQ context — skip for showcase (may contain financial hints)
    if (!isShowcase && faqContext && typeof faqContext === 'string') {
      systemContent += '\n' + faqContext
      systemContent += '\n\n## Versions-Datenvorrang (ABSOLUT VERBINDLICH)\nWenn die vorrecherchierten Antworten oben Zahlen, Beträge oder Details nennen, die von den "Unternehmensdaten" oder dem "Finanzplan-Liquidität" weiter oben abweichen, haben die Unternehmensdaten IMMER Vorrang. Die FAQ-Antworten sind allgemein formuliert und könnten veraltete oder szenario-fremde Zahlen enthalten. Nutze sie nur für Struktur und Formulierung — die konkreten Zahlen kommen ausschließlich aus den Unternehmensdaten dieses Investors.'
    }

    // Slide context for contextual awareness — filter hidden slides for showcase
    const visibleSlideOrder = isShowcase
      ? SLIDE_ORDER.filter(id => !SHOWCASE_HIDDEN_SLIDES.has(id))
      : SLIDE_ORDER

    if (slideContext) {
      const visited: number[] = slideContext.visitedSlides || []
      const currentSlideId = slideContext.currentSlide
      const currentSlideName = SLIDE_DISPLAY_NAMES[currentSlideId]?.[lang] || currentSlideId
      const notYetSeen = visibleSlideOrder
        .map((id, idx) => ({ id, idx, name: SLIDE_DISPLAY_NAMES[id]?.[lang] || id }))
        .filter(s => !visited.includes(s.idx))
        .map(s => `${s.idx + 1}. ${s.name}`)

      systemContent += `\n\n## Slide-Kontext (WICHTIG für kontextuelle Antworten)
- Aktuelle Slide: "${currentSlideName}" (Nr. ${slideContext.currentIndex + 1} von ${visibleSlideOrder.length})
- Bereits besuchte Slides: ${visited.map((i: number) => SLIDE_DISPLAY_NAMES[visibleSlideOrder[i]]?.[lang] || visibleSlideOrder[i]).filter(Boolean).join(', ')}
- Noch nicht gesehene Slides: ${notYetSeen.join(', ')}
- Ist Erstbesuch: ${visited.length <= 1 ? 'JA — Besucher hat gerade erst die Präsentation geöffnet' : 'Nein'}
- Verfügbare Slide-IDs für [GOTO:id]: ${visibleSlideOrder.join(', ')}
`
    }

    systemContent += `\n\n## Aktuelle Sprache: ${lang === 'de' ? 'Deutsch' : 'English'}\nAntworte in ${lang === 'de' ? 'Deutsch' : 'English'}.`

    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 + '\n\n(Erinnerung: Beende deine Antwort IMMER mit "---" gefolgt von 3 Folgefragen im Format "[Q] Frage?")' },
    ]

    // LiteLLM (OpenAI-compatible API)
    const headers: Record<string, string> = {
      'Content-Type': 'application/json',
    }
    if (LITELLM_API_KEY) {
      headers['Authorization'] = `Bearer ${LITELLM_API_KEY}`
    }

    const llmResponse = await fetch(`${LITELLM_URL}/v1/chat/completions`, {
      method: 'POST',
      headers,
      body: JSON.stringify({
        model: LITELLM_MODEL,
        messages,
        stream: true,
        temperature: 0.4,
        max_tokens: 4096,
      }),
      signal: AbortSignal.timeout(120000),
    })

    if (!llmResponse.ok) {
      const errorText = await llmResponse.text()
      console.error('LiteLLM error:', llmResponse.status, errorText.slice(0, 200))
      return NextResponse.json(
        { error: `LLM nicht erreichbar (Status ${llmResponse.status}).` },
        { status: 502 }
      )
    }

    // Parse SSE stream from LiteLLM and emit plain text to client
    const encoder = new TextEncoder()
    const stream = new ReadableStream({
      async start(controller) {
        const reader = llmResponse.body!.getReader()
        const decoder = new TextDecoder()
        let buffer = ''

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

            buffer += decoder.decode(value, { stream: true })
            const lines = buffer.split('\n')
            // Keep the last (potentially incomplete) line in the buffer
            buffer = lines.pop() || ''

            for (const line of lines) {
              const trimmed = line.trim()
              if (!trimmed || !trimmed.startsWith('data: ')) continue
              const data = trimmed.slice(6)
              if (data === '[DONE]') continue

              try {
                const json = JSON.parse(data)
                const content = json.choices?.[0]?.delta?.content
                if (content) {
                  controller.enqueue(encoder.encode(content))
                }
              } catch {
                // Partial JSON, skip
              }
            }
          }

          // Process any remaining buffer
          if (buffer.trim()) {
            const trimmed = buffer.trim()
            if (trimmed.startsWith('data: ') && trimmed.slice(6) !== '[DONE]') {
              try {
                const json = JSON.parse(trimmed.slice(6))
                const content = json.choices?.[0]?.delta?.content
                if (content) {
                  controller.enqueue(encoder.encode(content))
                }
              } catch {
                // Ignore
              }
            }
          }
        } catch (error) {
          console.error('Stream read error:', (error as Error).message)
        } 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('Investor agent chat error:', (error as Error).message)
    return NextResponse.json(
      { error: 'Verbindung zum LLM fehlgeschlagen.' },
      { status: 503 }
    )
  }
}
