<script setup>
/**
 * OCR-engine settings as a MODAL (opened from the inbox top-right). Default =
 * self-hosted (no LLM). The LLM is an optional plug-in: provider/baseUrl/model/
 * mode/threshold. The API key lives ONLY in the server env (AP_OCR_LLM_API_KEY).
 *
 * Persistence: PUT /api/accounting/incoming-invoices/config → stored per
 * organization in iDempiere AD_Preference (Attribute 'ap_ocr_llm'). After save we
 * re-load from the server so the form reflects what was actually persisted.
 */
import { reactive, ref, watch } from 'vue'

const { t } = useTranslation()
const props = defineProps({ open: { type: Boolean, default: false } })
const emit = defineEmits(['update:open'])

const cfg = reactive({ enabled: false, provider: 'compatible', baseUrl: '', model: '', mode: 'assisted', threshold: 0.6, hasKey: false, envEnabled: false })
const loading = ref(false)
const saving = ref(false)
const alert = ref({ status: 200, message: '' })

const load = async () => {
  loading.value = true
  alert.value = { status: 200, message: '' }
  try {
    const res = await $fetch('/api/accounting/incoming-invoices/config', { headers: useRequestHeaders(['cookie']) })
    if (res?.llm) Object.assign(cfg, res.llm)
  } catch (e) { alert.value = { status: 500, message: e?.message || 'Fehler beim Laden' } }
  finally { loading.value = false }
}

const save = async () => {
  saving.value = true
  alert.value = { status: 200, message: '' }
  try {
    const res = await $fetch('/api/accounting/incoming-invoices/config', {
      method: 'PUT', headers: useRequestHeaders(['cookie']),
      body: { enabled: cfg.enabled, provider: cfg.provider, baseUrl: cfg.baseUrl, model: cfg.model, mode: cfg.mode, threshold: cfg.threshold }
    })
    if (Number(res?.status) === 200) {
      await load() // reload from server → confirms it persisted
      alert.value = { status: 200, message: (t.value?.saved || 'Gespeichert') + ' ✓' }
    } else {
      alert.value = { status: res?.status || 500, message: res?.message || 'Fehler beim Speichern' }
    }
  } catch (e) { alert.value = { status: 500, message: e?.message || 'Fehler' } }
  finally { saving.value = false }
}

const close = () => emit('update:open', false)
watch(() => props.open, (v) => { if (v) load() })
</script>

<template>
  <div v-if="open" class="ovl" @click.self="close" @keydown.esc="close">
    <div class="modal-box" role="dialog" aria-modal="true">
      <header class="mb-head">
        <div class="mb-title"><i class="ti ti-settings"></i> {{ t.engine_settings || 'OCR-Engine' }}</div>
        <button class="mb-x" @click="close" aria-label="Close"><i class="ti ti-x"></i></button>
      </header>

      <div class="mb-body">
        <AlertBox :alert="alert" />

        <p class="muted">{{ t.engine_intro || 'Standard: selbst-gehostet (Tesseract/pdfjs + Lernen pro Lieferant). Optional kann ein LLM zugeschaltet werden.' }}</p>

        <label class="switch">
          <input type="checkbox" v-model="cfg.enabled" />
          <span>{{ t.enable_llm || 'LLM-Unterstützung aktivieren' }}</span>
        </label>

        <p v-if="cfg.enabled && !cfg.hasKey" class="warn">
          <i class="ti ti-alert-triangle"></i>
          {{ t.llm_key_missing || 'Kein API-Key gesetzt — AP_OCR_LLM_API_KEY muss in der Server-Umgebung (.env) konfiguriert sein, damit das LLM genutzt wird.' }}
        </p>

        <div v-if="cfg.enabled" class="grid2">
          <label class="lbl">{{ t.provider || 'Anbieter' }}</label>
          <select class="select" v-model="cfg.provider">
            <option value="compatible">OpenAI-compatible</option>
            <option value="openai">OpenAI</option>
            <option value="anthropic">Anthropic</option>
            <option value="ollama">Ollama / vLLM (lokal)</option>
          </select>

          <label class="lbl">Base URL</label>
          <input class="input" v-model="cfg.baseUrl" placeholder="https://api.openai.com/v1 · http://localhost:11434/v1" />

          <label class="lbl">{{ t.model || 'Modell' }}</label>
          <input class="input" v-model="cfg.model" placeholder="gpt-4o-mini · claude-… · llama3.1" />

          <label class="lbl">{{ t.llm_mode || 'Modus' }}</label>
          <select class="select" v-model="cfg.mode">
            <option value="assisted">{{ t.mode_assisted || 'Assistiert (nur bei niedriger Sicherheit)' }}</option>
            <option value="only">{{ t.mode_only || 'Immer LLM' }}</option>
          </select>

          <label class="lbl">{{ t.confidence_threshold || 'Schwellwert (Eskalation)' }}</label>
          <input class="input" type="number" min="0" max="1" step="0.05" v-model.number="cfg.threshold" />

          <label class="lbl">API-Key</label>
          <div class="keyline">
            <span class="tag" :class="cfg.hasKey ? 'is-success' : 'is-grey'">{{ cfg.hasKey ? (t.key_set || 'gesetzt (Server-Env)') : (t.key_unset || 'nicht gesetzt') }}</span>
            <span class="muted small">{{ t.key_env_only || 'Der Key wird nur serverseitig gespeichert.' }}</span>
          </div>
        </div>

        <p class="store-note">
          <i class="ti ti-database"></i>
          {{ t.config_stored_note || 'Gespeichert pro Organisation in iDempiere (AD_Preference · »ap_ocr_llm«). Der API-Key bleibt ausschließlich in der Server-.env.' }}
        </p>
      </div>

      <footer class="mb-foot">
        <button class="button is-light" @click="close" :disabled="saving">{{ t.cancel || 'Abbrechen' }}</button>
        <button class="button is-primary" @click="save" :disabled="saving || loading">
          <i class="ti" :class="saving ? 'ti-loader-2 spin' : 'ti-device-floppy'"></i> {{ t.save || 'Speichern' }}
        </button>
      </footer>
    </div>
  </div>
</template>

<style scoped>
.ovl {
  position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
  background: rgba(15, 23, 42, .55); backdrop-filter: blur(2px); padding: 20px;
}
.modal-box {
  width: 100%; max-width: 560px; max-height: 88vh; display: flex; flex-direction: column;
  background: var(--theme-bg-primary, #fff); border-radius: 16px; overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .35); border: 1px solid var(--theme-border, #e5e7eb);
}
.mb-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--theme-border, #eef0f3); }
.mb-title { font-weight: 800; font-size: 1.05rem; display: flex; align-items: center; gap: 8px; color: var(--theme-text-primary, #111); }
.mb-x { border: none; background: transparent; cursor: pointer; font-size: 1.15rem; color: var(--theme-text-secondary, #64748b); border-radius: 8px; width: 32px; height: 32px; }
.mb-x:hover { background: var(--theme-bg-secondary, #f1f5f9); }
.mb-body { padding: 20px; overflow: auto; }
.mb-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 14px 20px; border-top: 1px solid var(--theme-border, #eef0f3); background: var(--theme-bg-secondary, #f8fafc); }
.muted { color: var(--theme-text-secondary, #64748b); font-size: .86rem; margin-bottom: 14px; }
.muted.small { font-size: .76rem; }
.switch { display: flex; align-items: center; gap: 8px; font-weight: 600; margin-bottom: 12px; cursor: pointer; }
.warn { color: #b45309; font-size: .82rem; margin-bottom: 12px; display: flex; gap: 6px; align-items: flex-start; }
.grid2 { display: grid; grid-template-columns: 150px 1fr; gap: 12px 14px; align-items: center; }
.lbl { font-size: .85rem; color: var(--theme-text-secondary, #64748b); }
.input, .select { width: 100%; }
.keyline { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tag.is-grey { background: #e5e7eb; color: #374151; }
.store-note { margin-top: 18px; padding: 10px 12px; border-radius: 10px; background: var(--theme-bg-secondary, #f1f5f9); color: var(--theme-text-secondary, #64748b); font-size: .78rem; display: flex; gap: 8px; align-items: flex-start; }
.spin { animation: spin 1s linear infinite; display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }
</style>
