<template>
  <div class="ops-card q-mb-md">
    <div class="row items-center q-mb-xs">
      <q-icon name="hub" size="20px" color="deep-purple-6" class="q-mr-sm" />
      <span class="text-subtitle1 text-weight-bold">Modèles IA — routage & repli</span>
      <q-space />
      <q-spinner v-if="loading" size="16px" color="deep-purple-6" />
      <q-btn flat round dense icon="refresh" size="sm" @click="load"><q-tooltip>Rafraîchir</q-tooltip></q-btn>
    </div>
    <div class="text-caption text-grey-6 q-mb-md">
      Choisis le modèle par tâche. <b>Gemini</b> reste le <b>repli automatique</b> si le modèle local échoue ou est indisponible. Le plan de contrôle (scripts, solveur) reste déterministe — l'IA ne fait que proposer.
    </div>

    <!-- Profils -->
    <div class="row q-col-gutter-sm q-mb-md">
      <div class="col-12 col-sm-6" v-for="p in profiles" :key="p.name">
        <div class="prof-card" :class="{ avail: p.available }">
          <div class="row items-center no-wrap">
            <q-icon :name="p.name === 'gemini' ? 'cloud' : 'dns'" :color="p.available ? 'deep-purple-5' : 'grey-5'" class="q-mr-sm" />
            <div>
              <div class="text-weight-medium">{{ p.label }}</div>
              <div class="text-caption text-grey-6">{{ p.model || '—' }}<span v-if="p.base"> · {{ p.base }}</span></div>
            </div>
            <q-space />
            <q-badge :color="p.available ? 'green-2' : 'grey-3'" :text-color="p.available ? 'green-9' : 'grey-7'">{{ p.available ? 'disponible' : 'indisponible' }}</q-badge>
          </div>
        </div>
      </div>
    </div>

    <!-- Config du profil local -->
    <div class="local-cfg q-mb-md">
      <div class="text-subtitle2 q-mb-xs">Profil local (vLLM / Ollama → QWEN / Hermes)</div>
      <div class="row q-col-gutter-sm">
        <q-input class="col-12 col-sm-6" dense outlined v-model="local.baseUrl" label="URL base (OpenAI-compat)" placeholder="http://gpu-host:8000/v1/" hint="Slash final requis" />
        <q-input class="col-12 col-sm-6" dense outlined v-model="local.model" label="Modèle" placeholder="Qwen/Qwen2.5-14B-Instruct" />
      </div>
      <div v-if="!localKeySet" class="text-caption text-warning q-mt-xs">
        <q-icon name="warning" size="14px" /> Clé absente : définis <code>AI_LOCAL_API_KEY</code> dans <code>/opt/targo-hub/.env</code> (les secrets restent côté serveur, jamais dans l'UI), puis recrée le conteneur.
      </div>
      <div class="row items-center q-gutter-sm q-mt-sm">
        <q-btn dense outline color="deep-purple-6" icon="network_check" label="Tester la connexion" no-caps :loading="testing" :disable="!localAvailable" @click="testLocal" />
        <span v-if="testResult" :class="testResult.ok ? 'text-green-8' : 'text-negative'" class="text-caption">
          <q-icon :name="testResult.ok ? 'check_circle' : 'error'" size="14px" />
          {{ testResult.ok ? `OK · ${testResult.model} · ${testResult.latency_ms} ms` : ('Échec : ' + testResult.error) }}
        </span>
        <span v-else-if="!localAvailable" class="text-caption text-grey-6">Configure base + modèle + clé .env pour activer.</span>
      </div>
    </div>

    <!-- Routage par tâche -->
    <div class="text-subtitle2 q-mb-xs">Routage par tâche</div>
    <div v-for="t in tasks" :key="t" class="row items-center q-py-xs q-px-sm route-row">
      <q-icon :name="taskIcon(t)" size="18px" color="grey-7" class="q-mr-sm" />
      <div class="col">
        <div class="text-body2">{{ taskLabel(t) }}</div>
        <div v-if="routing[t] && routing[t].wanted === 'local' && routing[t].effective !== 'local'" class="text-caption text-warning">↳ replié sur Gemini (local indisponible)</div>
      </div>
      <q-btn-toggle v-model="wanted[t]" :options="toggleOptions" dense unelevated no-caps toggle-color="deep-purple-6" color="grey-3" text-color="grey-8" size="sm" />
    </div>

    <div class="row justify-end q-mt-md">
      <q-btn unelevated color="deep-purple-6" icon="save" label="Enregistrer le routage" no-caps :loading="saving" @click="save" />
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { useQuasar } from 'quasar'
import { HUB_URL } from 'src/config/hub'

const $q = useQuasar()
const loading = ref(false)
const saving = ref(false)
const profiles = ref([])
const tasks = ref([])
const routing = ref({})
const wanted = reactive({})
const local = reactive({ baseUrl: '', model: '' })
const localKeySet = ref(false)
const testing = ref(false)
const testResult = ref(null)

const TASK_LABELS = {
  triage: 'Triage courriels', nl: 'Copilote (langage naturel)', split: 'Scinder une conversation',
  sms: 'Répondeur SMS', roster: 'Copilote planification', dispatch: 'Dispatch (suggestions IA)',
  diagnose: 'Diagnostic réseau', outage: 'Analyse de panne',
}
const TASK_ICONS = {
  triage: 'mail', nl: 'auto_awesome', split: 'call_split', sms: 'sms',
  roster: 'event', dispatch: 'local_shipping', diagnose: 'troubleshoot', outage: 'warning',
}
function taskLabel (t) { return TASK_LABELS[t] || t }
function taskIcon (t) { return TASK_ICONS[t] || 'smart_toy' }

const localAvailable = computed(() => (profiles.value.find(p => p.name === 'local') || {}).available)
const toggleOptions = computed(() => [
  { label: 'Gemini', value: 'gemini' },
  { label: 'Local', value: 'local', disable: !localAvailable.value },
])

async function load () {
  loading.value = true
  try {
    const r = await fetch(`${HUB_URL}/ai/route-status`)
    if (r.ok) {
      const d = await r.json()
      profiles.value = d.profiles || []
      tasks.value = d.tasks || []
      routing.value = d.routing || {}
      for (const t of tasks.value) wanted[t] = (d.routing[t] && d.routing[t].wanted) || 'gemini'
      const loc = profiles.value.find(p => p.name === 'local') || {}
      local.baseUrl = loc.base ? (loc.base.endsWith('/') ? loc.base : loc.base + '/') : ''
      local.model = loc.model || ''
      localKeySet.value = !!loc.key_set
    }
  } catch (e) { /* */ } finally { loading.value = false }
}

async function save () {
  saving.value = true
  try {
    const routes = {}
    for (const t of tasks.value) routes[t] = wanted[t]
    const r = await fetch(`${HUB_URL}/ai/routes`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ routes, local: { baseUrl: local.baseUrl, model: local.model } }) })
    if (r.ok) { const d = await r.json(); profiles.value = d.profiles || profiles.value; routing.value = d.routing || routing.value; $q.notify({ type: 'positive', message: 'Routage IA enregistré' }) }
    else $q.notify({ type: 'negative', message: 'Échec sauvegarde' })
  } catch (e) { $q.notify({ type: 'negative', message: e.message }) } finally { saving.value = false }
}

async function testLocal () {
  testing.value = true; testResult.value = null
  try {
    const r = await fetch(`${HUB_URL}/ai/route-test`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ profile: 'local' }) })
    testResult.value = await r.json()
  } catch (e) { testResult.value = { ok: false, error: e.message } } finally { testing.value = false }
}

onMounted(load)
</script>

<style scoped>
.prof-card { border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px 12px; background: #fafafd; }
.prof-card.avail { border-color: #c4b5fd; background: #f5f3ff; }
.local-cfg { border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px; background: #fafbff; }
.route-row { border-bottom: 1px solid #f1f5f9; border-radius: 6px; transition: background .1s; }
.route-row:hover { background: #f5f3ff; }
code { background: #eef2ff; padding: 1px 5px; border-radius: 4px; font-size: .82em; }
</style>
