import { config } from '../config.js'
import { knowledgeService } from './knowledge_service.js'
import type { ChatMessage, KnowledgeEntry } from '../types.js'

export interface AssistantReply {
  content: string
  /** Žinių bazės šaltiniai, panaudoti atsakymui (RAG). */
  sources: { id: string; title: string }[]
  /** Ar atsakymą sugeneravo LLM, ar tai atsarginis (offline) režimas. */
  mode: 'llm' | 'fallback'
}

const SYSTEM_PROMPT_LT = `Tu esi A.R.K.A. — autonominis skaitmeninės pirmosios pagalbos asistentas, veikiantis atjungtas nuo interneto krizės metu.
Atsakyk RAMIAI, TRUMPAI ir KONKREČIAIS žingsniais. Pirmenybę teik saugumui.
Remkis pateiktu kontekstu iš lokalios žinių bazės. Jei informacijos nepakanka — aiškiai tai pasakyk ir nurodyk saugiausią bendrą veiksmą.
Kritinėse medicininėse situacijose visada paragink kreiptis į medikus, kai tik įmanoma.
Atsakyk ta kalba, kuria užduotas klausimas (numatytoji — lietuvių).`

/**
 * Lokalaus AI servisas: surenka kontekstą iš žinių bazės ir kreipiasi į lokalų
 * OpenAI-suderinamą LLM (Ollama / LM Studio / llama.cpp).
 *
 * Jei LLM nepasiekiamas, grąžina atsarginį atsakymą tiesiai iš žinių
 * bazės — taip „pirmoji skaitmeninė pagalba" veikia net be modelio.
 */
export class AiService {
  private responseLanguage(query: string): 'lt' | 'en' {
    const englishSignals = query.match(
      /\b(the|a|an|how|what|when|where|why|who|do|does|during|water|help|need|is|are|can|should|blackout)\b/gi
    )?.length ?? 0
    const lithuanianSignals = query.match(
      /\b(kaip|kas|kada|kur|kodėl|vanduo|vandens|pagalba|reikia|yra|gali|turėčiau|dingus)\b/gi
    )?.length ?? 0
    return englishSignals > lithuanianSignals ? 'en' : 'lt'
  }

  private buildContext(entries: KnowledgeEntry[]): string {
    return entries
      .map((e) => `### ${e.title.lt} / ${e.title.en}\n${e.body.lt}`)
      .join('\n\n')
  }

  private fallbackAnswer(query: string, entries: KnowledgeEntry[]): AssistantReply {
    const lang = this.responseLanguage(query)
    if (entries.length === 0) {
      return {
        mode: 'fallback',
        sources: [],
        content: lang === 'en'
          ? 'The local language model is unavailable and no matching knowledge-base entry was found. Rephrase the question using simpler terms or inspect the knowledge base manually.'
          : 'Lokalus kalbos modelis nepasiekiamas, o žinių bazėje tinkamos informacijos nerasta. Pabandykite performuluoti klausimą paprastesniais žodžiais arba patikrinkite žinių bazę rankiniu būdu.',
      }
    }
    const body = entries
      .map((e) => `• ${e.title[lang]}\n${e.body[lang]}`)
      .join('\n\n')
    return {
      mode: 'fallback',
      sources: entries.map((e) => ({ id: e.id, title: e.title[lang] })),
      content: (lang === 'en'
        ? 'The local model is unavailable — here is a direct extract from the offline knowledge base:\n\n'
        : 'Lokalus modelis nepasiekiamas — pateikiu tiesioginę ištrauką iš žinių bazės:\n\n') + body,
    }
  }

  async chat(messages: ChatMessage[]): Promise<AssistantReply> {
    const lastUser = [...messages].reverse().find((m) => m.role === 'user')
    const query = lastUser?.content ?? ''
    const hits = knowledgeService.search(query, 3)
    const contextEntries = hits.map((h) => h.entry)
    const context = this.buildContext(contextEntries)
    const lang = this.responseLanguage(query)

    const payloadMessages: ChatMessage[] = [
      { role: 'system', content: SYSTEM_PROMPT_LT },
      ...(context
        ? [
            {
              role: 'system' as const,
              content: `Kontekstas iš lokalios žinių bazės:\n\n${context}`,
            },
          ]
        : []),
      ...messages,
    ]

    const controller = new AbortController()
    const timer = setTimeout(() => controller.abort(), config.ai.timeoutMs)
    try {
      const res = await fetch(`${config.ai.baseUrl}/chat/completions`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${config.ai.apiKey}`,
        },
        body: JSON.stringify({
          model: config.ai.model,
          messages: payloadMessages,
          temperature: 0.3,
          stream: false,
        }),
        signal: controller.signal,
      })

      if (!res.ok) throw new Error(`LLM HTTP ${res.status}`)
      const data = (await res.json()) as {
        choices?: { message?: { content?: string } }[]
      }
      const content = data.choices?.[0]?.message?.content?.trim()
      if (!content) throw new Error('Tuščias LLM atsakymas')

      return {
        mode: 'llm',
        content,
        sources: contextEntries.map((e) => ({ id: e.id, title: e.title[lang] })),
      }
    } catch {
      // LLM nepasiekiamas — pereinama į atsarginį žinių bazės režimą.
      return this.fallbackAnswer(query, contextEntries)
    } finally {
      clearTimeout(timer)
    }
  }
}

export const aiService = new AiService()
