<script setup>
import { computed, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { api } from '../lib/api.js'
import { apiUmind, contexto } from '../lib/contexto.js'
import UiEmptyState from '../components/ui/UiEmptyState.vue'
import UiIcono from '../components/ui/UiIcono.vue'
import TabAuditoria from './agente/TabAuditoria.vue'
import TabConexiones from './agente/TabConexiones.vue'
import TabChat from './agente/TabChat.vue'
import TabConversaciones from './agente/TabConversaciones.vue'
import TabHerramientas from './agente/TabHerramientas.vue'
import TabCanales from './agente/TabCanales.vue'
import EstadoAgente from './agente/EstadoAgente.vue'
import PrimerosPasos from './agente/PrimerosPasos.vue'

const props = defineProps({
  tenantId: { type: String, required: true },
  agenteId: { type: String, required: true },
})
const agenteIdNum = computed(() => Number(props.agenteId))
const route = useRoute()

const agente = ref(null)
const error = ref('')
const tab = ref(
  typeof route.query.tab === 'string'
    ? route.query.tab
    : contexto.esPortal
      ? 'conversaciones'
      : 'conocimiento',
)

// ─── Base de conocimiento ───────────────────────────────────────────────────
const documentos = ref([])
const nuevaUrl = ref('')
const maxPaginas = ref(30)
const ingestando = ref(false)

async function cargarAgente() {
  const r = await api.get(apiUmind(`/umind/agentes?tenant_id=${props.tenantId}`))
  agente.value = (r.items || []).find((x) => String(x.ID) === props.agenteId) || null
}

async function cargarDocumentos() {
  const r = await api.get(apiUmind(`/umind/documentos?agente_id=${props.agenteId}`))
  documentos.value = r.items || []
}

// Tres formas de cargar conocimiento, no una: la web, un archivo (lista de
// precios, condiciones) y lo que el dueño escribe a mano, que es lo más
// valioso y lo único que no está en ningún documento.
const fuenteNueva = ref('texto')
const autoActualizar = ref(true)
const notaTitulo = ref('')
const notaTexto = ref('')
const archivoRef = ref(null)

async function agregarFuente() {
  if (!nuevaUrl.value.trim()) return
  ingestando.value = true
  error.value = ''
  try {
    await api.post(apiUmind('/umind/documentos'), {
      agente_id: agenteIdNum.value,
      url: nuevaUrl.value.trim(),
      max_paginas: Number(maxPaginas.value) || 30,
      auto_actualizar: autoActualizar.value,
    })
    nuevaUrl.value = ''
    await cargarDocumentos()
  } catch (e) {
    error.value = e.message
  } finally {
    ingestando.value = false
  }
}

async function agregarNota() {
  if (!notaTexto.value.trim()) return
  ingestando.value = true
  error.value = ''
  try {
    await api.post(apiUmind('/umind/documentos/texto'), {
      agente_id: agenteIdNum.value,
      titulo: notaTitulo.value.trim(),
      contenido: notaTexto.value,
    })
    notaTitulo.value = ''
    notaTexto.value = ''
    await cargarDocumentos()
  } catch (e) {
    error.value = e.message
  } finally {
    ingestando.value = false
  }
}

async function subirArchivo() {
  const f = archivoRef.value?.files?.[0]
  if (!f) return
  ingestando.value = true
  error.value = ''
  try {
    const fd = new FormData()
    fd.append('agente_id', String(agenteIdNum.value))
    fd.append('archivo', f)
    // Sin Content-Type a mano: el navegador tiene que poner el boundary.
    const res = await fetch(apiUmind('/umind/documentos/archivo'), { method: 'POST', body: fd })
    const data = await res.json()
    if (!res.ok) throw new Error(data.error || 'No se pudo subir')
    archivoRef.value.value = ''
    await cargarDocumentos()
  } catch (e) {
    error.value = e.message
  } finally {
    ingestando.value = false
  }
}

// Editar una fuente escrita a mano. Las plantillas de rubro dejan las notas
// con valores entre corchetes para reemplazar — sin esto, no había con qué.
// Ver qué se leyó de una fuente, fragmento por fragmento. Para un sitio
// crawleado es la única ventana: no tiene Editar (se rehace crawleando) y
// hasta ahora "9 fragmentos" era una caja negra.
const viendoDoc = ref(null)
const fragmentos = ref([])
const cargandoFragmentos = ref(false)

async function verFragmentos(d) {
  viendoDoc.value = d
  fragmentos.value = []
  cargandoFragmentos.value = true
  try {
    const r = await api.get(apiUmind(`/umind/documentos/${d.ID}/fragmentos`))
    fragmentos.value = r.items || []
  } catch (e) {
    error.value = e.message
    viendoDoc.value = null
  } finally {
    cargandoFragmentos.value = false
  }
}

const editandoDoc = ref(null)
const docForm = ref({ titulo: '', contenido: '' })
const guardandoDoc = ref(false)

function editarDocumento(d) {
  editandoDoc.value = d
  docForm.value = { titulo: d.origen, contenido: d.contenido || '' }
}

async function guardarDocumento() {
  if (!editandoDoc.value) return
  guardandoDoc.value = true
  error.value = ''
  try {
    await api.put(apiUmind(`/umind/documentos/${editandoDoc.value.ID}`), {
      titulo: docForm.value.titulo,
      contenido: docForm.value.contenido,
    })
    editandoDoc.value = null
    await cargarDocumentos()
  } catch (e) {
    error.value = e.message
  } finally {
    guardandoDoc.value = false
  }
}

async function reprocesar(d) {
  error.value = ''
  try {
    await api.post(apiUmind(`/umind/documentos/${d.ID}/reprocesar`), {})
    await cargarDocumentos()
  } catch (e) {
    error.value = e.message
  }
}

async function alternarAuto(d) {
  try {
    await api.put(apiUmind(`/umind/documentos/${d.ID}`), { auto_actualizar: !d.auto_actualizar })
    await cargarDocumentos()
  } catch (e) {
    error.value = e.message
  }
}

// "hace 3 días" en vez de una fecha: lo que importa no es cuándo se procesó
// sino qué tan viejo es lo que el agente está contestando.
function antiguedad(fecha) {
  if (!fecha) return 'sin procesar'
  const dias = Math.floor((Date.now() - new Date(fecha)) / 86400000)
  if (dias <= 0) return 'hoy'
  if (dias === 1) return 'ayer'
  if (dias < 30) return `hace ${dias} días`
  const meses = Math.floor(dias / 30)
  return meses === 1 ? 'hace un mes' : `hace ${meses} meses`
}

function estaVieja(d) {
  if (!d.procesado_at) return false
  return Date.now() - new Date(d.procesado_at) > 60 * 86400000
}

async function eliminarDocumento(id) {
  if (!confirm('¿Eliminar esta fuente y sus fragmentos indexados?')) return
  await api.del(apiUmind(`/umind/documentos/${id}`))
  await cargarDocumentos()
}

const estadoColor = computed(() => (estado) => ({
  listo: 'badge-ok',
  procesando: 'badge-alerta',
  pendiente: 'badge-neutro',
  error: 'badge-error',
}[estado] || 'badge-neutro'))

// ─── Conversaciones ──────────────────────────────────────────────────────────
const sesiones = ref([])
async function cargarSesiones() {
  const r = await api.get(apiUmind(`/umind/sesiones?agente_id=${props.agenteId}`))
  sesiones.value = r.items || []
}

// ─── Herramientas ───────────────────────────────────────────────────────────
const tools = ref([])

async function cargarTools() {
  const r = await api.get(apiUmind(`/umind/tools?agente_id=${props.agenteId}`))
  tools.value = r.items || []
}

// ─── Canales ────────────────────────────────────────────────────────────────
const canales = ref([])

async function cargarCanales() {
  const r = await api.get(apiUmind(`/umind/canales?agente_id=${props.agenteId}`))
  canales.value = r.items || []
}

// El enlace del reporte vive acá y no en la pestaña de canales: lo usa el
// encabezado, que se ve en todas.
const urlReporte = computed(() => {
  const hoy = new Date()
  const desde = new Date(hoy.getFullYear(), hoy.getMonth(), 1).toISOString().slice(0, 10)
  const hasta = hoy.toISOString().slice(0, 10)
  return apiUmind(`/umind/reporte.xlsx?agente_id=${props.agenteId}&desde=${desde}&hasta=${hasta}`)
})

// ─── Conexiones (correo, OAuth) ────────────────────────────────────────────────
const conexiones = ref([])

async function cargarConexiones() {
  const r = await api.get(apiUmind(`/umind/conexiones?agente_id=${props.agenteId}`))
  conexiones.value = r.items || []
}

// Tres zonas en vez de siete pestañas. Las siete eran nuestras siete tablas
// —documentos, tools, canales, conexiones, eventos— y un dueño de negocio no
// piensa "voy a Conexiones": piensa "¿por qué contestó mal?" o "quiero que
// sepa mis precios nuevos".
//
// Lo que se usa todos los días queda arriba; lo que se toca una vez y se
// olvida, en Avanzado.
const ZONAS = [
  ['conversaciones', 'Conversaciones'],
  ['conocimiento', 'Lo que sabe'],
  ['canales', 'Dónde atiende'],
]

// "Lo que sabe" agrupa todo lo que alimenta las respuestas: la información
// cargada, las casillas que puede consultar y las herramientas que puede
// llamar. Son tres formas de saber, no tres pantallas sueltas.
const SUBSECCIONES_SABE = [
  ['conocimiento', 'Información'],
  ['conexiones', 'Cuentas de correo'],
  ['herramientas', 'Herramientas'],
]

const enLoQueSabe = computed(() => SUBSECCIONES_SABE.some(([k]) => k === tab.value))

const AVANZADO = [['auditoria', 'Problemas']]

// La guía se muestra hasta que sabe algo Y atiende en algún lado. Probar es
// deseable pero no bloquea: nadie queda preso de la guía por no haber chateado.
const configurando = computed(
  () => !documentos.value.some((d) => d.estado === 'listo') || !canales.value.some((c) => c.activo),
)

const mostrarAvanzado = ref(false)

// Si se entra directo a una pestaña avanzada (por la URL o desde el estado de
// arriba), la sección tiene que verse abierta o el botón activo queda
// escondido detrás de un "Avanzado" cerrado.
if (AVANZADO.some(([k]) => k === tab.value)) mostrarAvanzado.value = true

function irA(destino) {
  tab.value = destino
  if (AVANZADO.some(([k]) => k === destino)) mostrarAvanzado.value = true
}

// ─── Auditoría ────────────────────────────────────────────────────────────────
const eventos = ref([])

async function cargarEventos() {
  const r = await api.get(apiUmind(`/umind/eventos?agente_id=${props.agenteId}`))
  eventos.value = r.items || []
}

// Se observan los dos parámetros: al saltar de un agente a otro (o a un
// agente de otro tenant) vue-router reusa la instancia y onMounted no vuelve
// a correr, así que la pantalla quedaba con los datos del agente anterior.
watch(
  () => [props.tenantId, props.agenteId],
  async () => {
    error.value = ''
    // Se limpia antes de pedir: si no, durante la carga se ven los datos del
    // agente anterior bajo el nombre del nuevo.
    agente.value = null
    documentos.value = []
    sesiones.value = []
    tools.value = []
    canales.value = []
    conexiones.value = []
    eventos.value = []
    try {
      await Promise.all([cargarAgente(), cargarDocumentos(), cargarSesiones(), cargarTools(), cargarCanales(), cargarConexiones(), cargarEventos()])
    } catch (e) {
      error.value = e.message
    }
  },
  { immediate: true },
)
</script>

<template>
  <div>
    <router-link :to="`/tenants/${tenantId}`" class="label hover:text-brand">&larr; Agentes</router-link>

    <div v-if="agente" class="mb-4 mt-1 flex items-start justify-between gap-4">
      <h1 class="text-xl font-semibold text-texto min-w-0 truncate">{{ agente.nombre }}</h1>
      <!-- Un archivo que se reenvía sirve para justificar el gasto puertas
           adentro; un panel al que hay que entrar, no. -->
      <a :href="urlReporte" class="btn-ghost shrink-0" title="Conversaciones y consumo del mes en Excel">
        <UiIcono nombre="descargar" :tam="15" /> Reporte del mes
      </a>
    </div>

    <!-- Mientras el agente esté a medio configurar, la guía de puesta en
         marcha; después, el estado de todos los días. Nunca los dos: dos
         resúmenes a la vez es no tener ninguno. -->
    <PrimerosPasos
      v-if="agente && configurando"
      :documentos="documentos"
      :canales="canales"
      :sesiones="sesiones"
      @ir="irA"
    />
    <EstadoAgente
      v-else-if="agente"
      :canales="canales"
      :documentos="documentos"
      :sesiones="sesiones"
      :eventos="eventos"
      @ir="irA"
    />

    <p v-if="error" class="text-sm text-red-600 dark:text-red-400 mb-4">{{ error }}</p>

    <div class="flex items-center gap-1.5 mb-6 flex-wrap">
      <button
        v-for="[key, label] in ZONAS"
        :key="key"
        class="px-3.5 py-1.5 rounded-full text-sm whitespace-nowrap transition-colors"
        :class="(key === 'conocimiento' ? enLoQueSabe : tab === key)
          ? 'bg-brand text-white font-medium'
          : 'bg-white dark:bg-gray-900 text-gray-600 dark:text-gray-400 border border-borde hover:border-brand/50'"
        @click="tab = key"
      >
        {{ label }}
      </button>

      <!-- Lo que se configura una vez no puede competir todos los días con lo
           que se mira todos los días. -->
      <button
        class="ml-auto text-xs text-tenue hover:text-texto inline-flex items-center gap-1"
        @click="mostrarAvanzado = !mostrarAvanzado"
      >
        Avanzado
        <span class="text-[10px]">{{ mostrarAvanzado ? '▲' : '▼' }}</span>
      </button>
    </div>

    <div v-if="enLoQueSabe" class="flex gap-1.5 mb-6 flex-wrap -mt-3">
      <button
        v-for="[key, label] in SUBSECCIONES_SABE"
        :key="key"
        class="px-3 py-1 rounded-full text-xs whitespace-nowrap transition-colors"
        :class="tab === key
          ? 'bg-brand/15 text-brand font-medium border border-brand/40'
          : 'text-tenue border border-transparent hover:text-texto'"
        @click="tab = key"
      >
        {{ label }}
      </button>
    </div>

    <div v-if="mostrarAvanzado" class="flex gap-1.5 mb-6 flex-wrap">
      <button
        v-for="[key, label] in AVANZADO"
        :key="key"
        class="px-3 py-1 rounded-full text-xs whitespace-nowrap transition-colors"
        :class="tab === key
          ? 'bg-texto text-white dark:bg-gray-200 dark:text-gray-900 font-medium'
          : 'bg-white dark:bg-gray-900 text-tenue border border-borde hover:border-brand/50'"
        @click="tab = key"
      >
        {{ label }}
      </button>
    </div>

    <!-- Lo que sabe: el conocimiento y la prueba, lado a lado.
         El bucle real es leer lo que sabe → probar → corregir → probar de
         nuevo. Con las dos cosas en pestañas separadas, eso eran seis clics
         por corrección; acá es escribir y ver. -->
    <div v-if="tab === 'conocimiento'" class="grid gap-4 lg:grid-cols-[1fr_21rem] items-start">
      <div>
      <div class="card p-4 mb-4">
        <div class="flex gap-1 mb-3">
          <button
            v-for="[k, ico, l] in [['texto', 'escribir', 'Escribir'], ['archivo', 'archivo', 'Subir archivo'], ['url', 'sitio', 'Sitio web']]"
            :key="k"
            class="px-3 py-1.5 rounded-lg text-sm inline-flex items-center gap-1.5"
            :class="fuenteNueva === k ? 'bg-brand text-white font-medium' : 'text-tenue hover:text-texto'"
            @click="fuenteNueva = k"
          ><UiIcono :nombre="ico" :tam="15" /> {{ l }}</button>
        </div>

        <!-- Lo que el dueño sabe y no está escrito en ningún lado. -->
        <form v-if="fuenteNueva === 'texto'" class="space-y-2" @submit.prevent="agregarNota">
          <input v-model="notaTitulo" placeholder="Título (ej: Horarios y zonas de entrega)" class="input" />
          <textarea
            v-model="notaTexto"
            rows="5"
            required
            placeholder="Atendemos de lunes a viernes de 9 a 18. No hacemos envíos fuera de la ciudad. La garantía es de 6 meses y cubre…"
            class="input font-normal"
          ></textarea>
          <div class="flex items-center justify-between">
            <p class="text-xs text-tenue">Lo que te preguntan todos los días y no está en tu web.</p>
            <button type="submit" :disabled="ingestando" class="btn-primary disabled:opacity-50">
              {{ ingestando ? 'Guardando…' : 'Guardar' }}
            </button>
          </div>
        </form>

        <form v-else-if="fuenteNueva === 'archivo'" class="space-y-2" @submit.prevent="subirArchivo">
          <input ref="archivoRef" type="file" accept=".pdf,.docx,.txt,.md,.csv,.html,image/*" class="text-sm text-texto" />
          <div class="flex items-center justify-between">
            <p class="text-xs text-tenue">PDF, Word, texto o una foto. Ej: tu lista de precios.</p>
            <button type="submit" :disabled="ingestando" class="btn-primary disabled:opacity-50">
              {{ ingestando ? 'Leyendo…' : 'Subir' }}
            </button>
          </div>
        </form>

        <form v-else class="space-y-2" @submit.prevent="agregarFuente">
          <div class="flex gap-2">
            <input v-model="nuevaUrl" type="url" placeholder="https://ejemplo.com" required class="input flex-1" />
            <input v-model="maxPaginas" type="number" min="1" max="200" class="input w-24" title="Máximo de páginas a leer" />
          </div>
          <div class="flex items-center justify-between">
            <label class="flex items-center gap-2 text-xs text-tenue cursor-pointer">
              <input v-model="autoActualizar" type="checkbox" class="rounded border-borde text-brand focus:ring-brand" />
              Releer el sitio cada semana
            </label>
            <button type="submit" :disabled="ingestando" class="btn-primary disabled:opacity-50">
              {{ ingestando ? 'Leyendo…' : 'Leer sitio' }}
            </button>
          </div>
        </form>
      </div>
      <div class="card divide-y divide-borde">
        <UiEmptyState
          v-if="documentos.length === 0"
          estado="buscando"
          titulo="Todavía no sabe nada de tu negocio"
          detalle="Sin información cargada va a contestar que no sabe. Empezá por escribir tus horarios y lo que te preguntan todos los días — es lo más rápido y lo que más se nota."
        />
        <div v-for="d in documentos" :key="d.ID" class="p-4 flex items-center justify-between">
          <div>
            <div class="text-sm text-texto">{{ d.origen }}</div>
            <div class="text-xs text-tenue mt-0.5">
              <span class="px-1.5 py-0.5 rounded inline-flex items-center gap-1" :class="estadoColor(d.estado)">
                <span v-if="d.estado === 'procesando'" class="latido"></span>
                {{ d.estado }}
              </span>
              <span v-if="d.tipo"> · {{ { url: 'sitio', archivo: 'archivo', texto: 'nota' }[d.tipo] || d.tipo }}</span>
              <span v-if="d.total_chunks"> · {{ d.total_chunks }} fragmentos</span>
              <!-- La antigüedad, en rojo cuando pasó de dos meses: es lo único
                   que delata que el agente contesta con información vieja. -->
              <span v-if="d.procesado_at" :class="estaVieja(d) ? 'text-amber-600 dark:text-amber-400 font-medium' : ''">
                · leído {{ antiguedad(d.procesado_at) }}
              </span>
              <span v-if="d.auto_actualizar"> · se actualiza sola</span>
              <span v-if="d.error" class="text-red-600 dark:text-red-400"> · {{ d.error }}</span>
            </div>
          </div>
          <div class="flex items-center gap-3 shrink-0">
            <button
              v-if="d.tipo === 'url'"
              class="text-xs text-tenue hover:text-texto"
              :title="d.auto_actualizar ? 'Dejar de releer sola' : 'Releer el sitio cada semana'"
              @click="alternarAuto(d)"
            ><UiIcono :nombre="d.auto_actualizar ? 'auto' : 'refrescar'" :tam="13" class="mr-1" />{{ d.auto_actualizar ? 'auto' : 'manual' }}</button>
            <button
              class="text-sm text-tenue hover:text-texto"
              :disabled="!d.total_chunks"
              :class="!d.total_chunks ? 'opacity-40 cursor-default' : ''"
              title="Ver qué se leyó de esta fuente"
              @click="verFragmentos(d)"
            >Ver</button>
            <!-- Solo lo que tiene texto propio guardado: una URL se rehace
                 crawleando, editarla a mano se perdería en la próxima pasada. -->
            <button
              v-if="d.tipo === 'texto' || d.tipo === 'archivo'"
              class="text-sm text-brand hover:underline"
              @click="editarDocumento(d)"
            >Editar</button>
            <button
              class="text-sm text-tenue hover:text-texto disabled:opacity-40"
              :disabled="d.estado === 'procesando'"
              :title="d.tipo === 'url' ? 'Volver a leer el sitio' : 'Rehacer los fragmentos'"
              @click="reprocesar(d)"
            >Actualizar</button>
            <button class="text-red-500 hover:text-red-700 text-sm" @click="eliminarDocumento(d.ID)">Eliminar</button>
          </div>
        </div>
      </div>

      </div>

      <!-- La prueba, al lado y siempre visible mientras se edita el
           conocimiento. En pantallas angostas cae abajo, que es el orden en
           que igual se trabaja. -->
      <div class="lg:sticky lg:top-4">
        <p class="label mb-2">Probalo</p>
        <TabChat :agente-id="agenteIdNum" />
      </div>

      <!-- Ver los fragmentos de una fuente, solo lectura -->
      <div
        v-if="viendoDoc"
        class="fixed inset-0 bg-black/40 flex items-center justify-center p-4 z-50"
        @click.self="viendoDoc = null"
      >
        <div class="card w-full max-w-2xl p-6 max-h-[calc(100vh-2rem)] overflow-y-auto">
          <div class="flex items-baseline justify-between gap-3 mb-1">
            <h2 class="font-semibold text-texto truncate">{{ viendoDoc.origen }}</h2>
            <span class="text-xs text-tenue shrink-0 tabular-nums">
              {{ fragmentos.length }} {{ fragmentos.length === 1 ? 'fragmento' : 'fragmentos' }}
            </span>
          </div>
          <p class="text-xs text-tenue mb-4">
            Esto es exactamente lo que el asistente puede consultar de esta fuente.
            Si acá falta algo o se leyó mal, eso mismo le va a faltar en las respuestas.
          </p>

          <p v-if="cargandoFragmentos" class="text-sm text-tenue">Cargando…</p>
          <div v-else class="space-y-2">
            <div
              v-for="(f, i) in fragmentos"
              :key="f.ID"
              class="bg-elevado border border-borde rounded-lg p-3 text-sm text-texto whitespace-pre-wrap"
            >
              <span class="text-[10px] text-tenue tabular-nums block mb-1">#{{ i + 1 }}</span>{{ f.contenido }}
            </div>
          </div>

          <div class="flex justify-end pt-4">
            <button class="btn-ghost" @click="viendoDoc = null">Cerrar</button>
          </div>
        </div>
      </div>

      <!-- Editar una nota o el texto extraído de un archivo -->
      <div
        v-if="editandoDoc"
        class="fixed inset-0 bg-black/40 flex items-center justify-center p-4 z-50"
        @click.self="editandoDoc = null"
      >
        <div class="card w-full max-w-2xl p-6 max-h-[calc(100vh-2rem)] overflow-y-auto">
          <h2 class="font-semibold text-texto mb-1">Editar fuente</h2>
          <p class="text-xs text-tenue mb-4">
            Al guardar se vuelve a leer y el agente empieza a contestar con esto.
          </p>

          <form class="space-y-3" @submit.prevent="guardarDocumento">
            <div>
              <label class="label">Título</label>
              <input v-model="docForm.titulo" required class="input" />
            </div>
            <div>
              <label class="label">Contenido</label>
              <textarea
                v-model="docForm.contenido"
                rows="16"
                required
                class="input font-normal leading-relaxed"
              ></textarea>
              <p class="text-xs text-tenue mt-1.5">
                Si viene de una plantilla, reemplazá lo que está [entre corchetes] por tus datos.
                Lo que quede sin reemplazar el agente lo va a leer tal cual.
              </p>
            </div>
            <div class="flex justify-end gap-2 pt-1">
              <button type="button" class="btn-ghost" @click="editandoDoc = null">Cancelar</button>
              <button type="submit" class="btn-primary" :disabled="guardandoDoc">
                {{ guardandoDoc ? 'Guardando…' : 'Guardar y volver a leer' }}
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- Herramientas -->
    <TabHerramientas
      v-else-if="tab === 'herramientas'"
      :agente-id="agenteIdNum"
      :tools="tools"
      @recargar="cargarTools"
      @error="(m) => (error = m)"
    />

    <TabCanales
      v-else-if="tab === 'canales'"
      :agente-id="agenteIdNum"
      :site-key="agente?.site_key || ''"
      :canales="canales"
      @recargar="cargarCanales"
      @error="(m) => (error = m)"
    />

    <TabConexiones
      v-else-if="tab === 'conexiones'"
      :agente-id="agenteIdNum"
      :conexiones="conexiones"
      @recargar="cargarConexiones"
    />

    <!-- Chat de prueba -->
    <TabChat v-else-if="tab === 'chat'" :agente-id="agenteIdNum" />

    <!-- Conversaciones -->
    <TabConversaciones
      v-else-if="tab === 'conversaciones'"
      :agente-id="agenteIdNum"
      :sesiones="sesiones"
    />

    <!-- Auditoría -->
    <TabAuditoria v-else :eventos="eventos" />
  </div>
</template>
