<!-- src/views/pages/saas/SaasDocsPage.vue -->
<!-- SaaS admin: CRUD de documentação dinâmica exibida nas páginas do sistema -->
<script setup>
import { ref, computed, onMounted } from 'vue'
import { supabase } from '@/lib/supabase/client'
import { useToast } from 'primevue/usetoast'
import { useConfirm } from 'primevue/useconfirm'
import Editor from 'primevue/editor'
import { FilterMatchMode } from '@primevue/core/api'
import { PAGE_OPTIONS } from '@/utils/menuPageOptions'
import { invalidateAjudaCache } from '@/composables/useAjuda'
import { useDocsAdmin } from '@/composables/useDocsAdmin'
import { useDocsHealth } from '@/composables/useDocsHealth'

const toast   = useToast()
const confirm = useConfirm()
const { consumePendingEdit } = useDocsAdmin()
const {
  setDocs, saudeDoc, pctNegativo,
  totalDocs, docsAtencao, docsOk, docsSemDados,
  countAtencao, docMaisUtil, sortBySaude,
} = useDocsHealth()

// ── Estado ────────────────────────────────────────────────────
const loading = ref(false)
const docs    = ref([])

// ── Dialog ────────────────────────────────────────────────────
const dlgOpen    = ref(false)
const saving     = ref(false)
const editId     = ref(null)
const activeTab  = ref(0)   // 0 = Conteúdo, 1 = FAQ, 2 = Mídias, 3 = Configurações
const form       = ref(emptyForm())

function emptyForm () {
  return {
    titulo:            '',
    conteudo:          '',
    categoria:         '',
    exibir_no_faq:     false,
    tipo_acesso:       'usuario',
    pagina_path:       null,
    medias:            [],
    docs_relacionados: [],
    ativo:             true,
    ordem:             0,
    _custom_path:      '',
    _faq_itens:        []
  }
}

const tipoAcessoOptions = [
  { label: 'Usuários (todos)',                         value: 'usuario' },
  { label: 'Admin (clinic_admin, tenant_admin, saas)', value: 'admin' },
]

// ── Categorias dinâmicas ──────────────────────────────────────
const categorias = computed(() => {
  const set = new Set(docs.value.map(d => d.categoria).filter(Boolean))
  return [...set].sort()
})

// ── Opções de página ──────────────────────────────────────────
const pageSelectOptions = computed(() => [
  ...PAGE_OPTIONS,
  { label: '— Caminho personalizado —', path: '__custom__' }
])

const isCustomPath = computed(() => form.value.pagina_path === '__custom__')

// Contagem de docs por path (excluindo o próprio doc em edição)
const docsCountByPath = computed(() => {
  const map = new Map()
  for (const d of docs.value) {
    if (d.id === editId.value) continue
    if (!d.pagina_path) continue
    map.set(d.pagina_path, (map.get(d.pagina_path) || 0) + 1)
  }
  return map
})

const resolvedPath = computed(() => {
  if (isCustomPath.value) return form.value._custom_path.trim()
  return form.value.pagina_path || ''
})

// ── Docs relacionados (MultiSelect) ───────────────────────────
const docsRelOptions = computed(() =>
  docs.value
    .filter(d => d.id !== editId.value)
    .map(d => ({
      label: `${d.titulo}  ·  ${d.pagina_path}`,
      value: d.id
    }))
)

const formValid = computed(() =>
  !!form.value.titulo.trim() && !!resolvedPath.value
)

// ── Dialog abrir ──────────────────────────────────────────────
async function abrirDialog (doc = null) {
  activeTab.value = 0
  if (doc) {
    editId.value = doc.id
    const isCustom = !PAGE_OPTIONS.find(p => p.path === doc.pagina_path)
    form.value = {
      titulo:            doc.titulo || '',
      conteudo:          doc.conteudo || '',
      categoria:         doc.categoria || '',
      exibir_no_faq:     doc.exibir_no_faq ?? false,
      tipo_acesso:       doc.tipo_acesso || 'usuario',
      pagina_path:       isCustom ? '__custom__' : doc.pagina_path,
      medias:            Array.isArray(doc.medias)
                           ? JSON.parse(JSON.stringify(doc.medias))
                           : [],
      docs_relacionados: Array.isArray(doc.docs_relacionados)
                           ? [...doc.docs_relacionados]
                           : [],
      ativo:             doc.ativo ?? true,
      ordem:             doc.ordem ?? 0,
      _custom_path:      isCustom ? doc.pagina_path : '',
      _faq_itens:        []
    }
    // Carrega FAQ itens existentes
    await carregarFaqItens(doc.id)
  } else {
    editId.value = null
    form.value = emptyForm()
  }
  dlgOpen.value = true
}

// ── FAQ Itens ─────────────────────────────────────────────────
const faqLoading = ref(false)

async function carregarFaqItens (docId) {
  faqLoading.value = true
  try {
    const { data, error } = await supabase
      .from('saas_faq_itens')
      .select('id, pergunta, resposta, ordem, ativo')
      .eq('doc_id', docId)
      .order('ordem')
    if (error) throw error
    form.value._faq_itens = (data || []).map(item => ({
      ...item,
      _dirty: false,   // marcador de alteração local
      _novo:  false
    }))
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro ao carregar FAQ', detail: e?.message, life: 3000 })
  } finally {
    faqLoading.value = false
  }
}

function addFaqItem () {
  form.value._faq_itens.push({
    id:       null,
    pergunta: '',
    resposta: '',
    ordem:    form.value._faq_itens.length,
    ativo:    true,
    _dirty:   true,
    _novo:    true
  })
}

function removeFaqItem (idx) {
  form.value._faq_itens.splice(idx, 1)
}

// Salva os itens FAQ após salvar o doc
async function salvarFaqItens (docId) {
  const itens = form.value._faq_itens

  // Identifica itens para deletar (que existiam mas foram removidos)
  // — isso é tratado pelo splice + controle de _novo

  // Upsert dos que existem na lista
  for (let i = 0; i < itens.length; i++) {
    const item = itens[i]
    if (!item.pergunta.trim()) continue

    const payload = {
      doc_id:   docId,
      pergunta: item.pergunta.trim(),
      resposta: item.resposta || '',
      ordem:    i,
      ativo:    item.ativo ?? true,
      updated_at: new Date().toISOString()
    }

    if (item._novo || !item.id) {
      const { data, error } = await supabase
        .from('saas_faq_itens')
        .insert(payload)
        .select('id')
        .single()
      if (error) throw error
      itens[i].id   = data.id
      itens[i]._novo = false
    } else {
      const { error } = await supabase
        .from('saas_faq_itens')
        .update(payload)
        .eq('id', item.id)
      if (error) throw error
    }
    itens[i]._dirty = false
  }

  // Remove do banco itens que foram deletados da lista
  // (busca ids que existiam e não estão mais na lista)
  if (editId.value) {
    const idsAtuais = itens.map(i => i.id).filter(Boolean)
    const { data: existentes } = await supabase
      .from('saas_faq_itens')
      .select('id')
      .eq('doc_id', docId)
    const existentesIds = (existentes || []).map(e => e.id)
    const paraExcluir = existentesIds.filter(id => !idsAtuais.includes(id))
    if (paraExcluir.length) {
      await supabase
        .from('saas_faq_itens')
        .delete()
        .in('id', paraExcluir)
    }
  }
}

// ── Mídias ────────────────────────────────────────────────────
function addMedia ()       { form.value.medias.push({ tipo: 'imagem', url: '' }) }
function removeMedia (idx) { form.value.medias.splice(idx, 1) }

const uploadingIdx  = ref(new Set())
const fileInputRefs = ref({})

function triggerUpload (idx) {
  fileInputRefs.value[idx]?.click()
}

async function uploadImagem (idx, event) {
  const file = event.target.files?.[0]
  if (!file) return
  event.target.value = ''
  const ext  = file.name.split('.').pop()
  const nome = `${crypto.randomUUID()}.${ext}`
  const path = `doc-images/${nome}`
  uploadingIdx.value = new Set([...uploadingIdx.value, idx])
  try {
    const { error: upErr } = await supabase.storage
      .from('saas-docs')
      .upload(path, file, { upsert: false, contentType: file.type })
    if (upErr) throw upErr
    const { data } = supabase.storage.from('saas-docs').getPublicUrl(path)
    form.value.medias[idx].url = data.publicUrl
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro no upload', detail: e?.message, life: 4000 })
  } finally {
    const next = new Set(uploadingIdx.value)
    next.delete(idx)
    uploadingIdx.value = next
  }
}

// ── Salvar ────────────────────────────────────────────────────
async function salvar () {
  if (!formValid.value) return
  saving.value = true
  try {
    const payload = {
      titulo:            form.value.titulo.trim(),
      conteudo:          form.value.conteudo.trim(),
      categoria:         form.value.categoria.trim() || null,
      exibir_no_faq:     form.value.exibir_no_faq,
      tipo_acesso:       form.value.tipo_acesso,
      pagina_path:       resolvedPath.value,
      medias:            form.value.medias.filter(m => m.url.trim()),
      docs_relacionados: form.value.docs_relacionados,
      ativo:             form.value.ativo,
      ordem:             Number(form.value.ordem) || 0,
      updated_at:        new Date().toISOString()
    }

    let docId = editId.value

    if (editId.value) {
      const { error } = await supabase
        .from('saas_docs')
        .update(payload)
        .eq('id', editId.value)
      if (error) throw error
      const idx = docs.value.findIndex(d => d.id === editId.value)
      if (idx >= 0) docs.value[idx] = { ...docs.value[idx], ...payload, id: editId.value }
      toast.add({ severity: 'success', summary: 'Documento atualizado', life: 1800 })
    } else {
      const { data, error } = await supabase
        .from('saas_docs')
        .insert(payload)
        .select()
        .single()
      if (error) throw error
      docId = data.id
      docs.value = [data, ...docs.value]
      toast.add({ severity: 'success', summary: 'Documento criado', life: 1800 })
    }

    // Salva itens FAQ
    await salvarFaqItens(docId)

    invalidateAjudaCache(resolvedPath.value)
    dlgOpen.value = false
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3500 })
  } finally {
    saving.value = false
  }
}

// ── Excluir ───────────────────────────────────────────────────
function excluir (doc) {
  confirm.require({
    header:      'Excluir documento',
    message:     `Tem certeza que deseja excluir "${doc.titulo}"? Esta ação não pode ser desfeita.`,
    icon:        'pi pi-exclamation-triangle',
    acceptLabel: 'Excluir',
    rejectLabel: 'Cancelar',
    acceptClass: 'p-button-danger',
    accept: async () => {
      try {
        const { error } = await supabase
          .from('saas_docs')
          .delete()
          .eq('id', doc.id)
        if (error) throw error
        docs.value = docs.value.filter(d => d.id !== doc.id)
        invalidateAjudaCache(doc.pagina_path)
        toast.add({ severity: 'success', summary: 'Documento removido', life: 1800 })
      } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao excluir', detail: e?.message, life: 3000 })
      }
    }
  })
}

// ── Load ──────────────────────────────────────────────────────
async function load () {
  loading.value = true
  try {
    const { data, error } = await supabase
      .from('saas_docs')
      .select('*')
      .order('pagina_path')
      .order('ordem')
    if (error) throw error
    docs.value = data || []
    console.log('docs carregados:', docs.value.map(d => ({ titulo: d.titulo, votos_util: d.votos_util, votos_nao_util: d.votos_nao_util })))
    setDocs(docs.value)
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3500 })
  } finally {
    loading.value = false
  }
}

// ── Docs ordenados por saúde (problemáticos primeiro) ────────
const filtroAtencao = ref(false)   // toggle para mostrar só problemáticos

const docsFiltrados = computed(() => {
  let lista = docs.value
  if (filtroAtencao.value) lista = lista.filter(d => saudeDoc(d) === 'atencao')
  return sortBySaude(lista)
})

onMounted(async () => {
  await load()
  // Verifica se veio da página de FAQ com um doc para editar
  const pendingId = consumePendingEdit()
  if (pendingId) {
    const doc = docs.value.find(d => d.id === pendingId)
    if (doc) abrirDialog(doc)
  }
})

// ── Busca / Filtros ───────────────────────────────────────────
const filters = ref({
  global: { value: null, matchMode: FilterMatchMode.CONTAINS }
})

// ── Formatação de datas ───────────────────────────────────────
function fmtDate (iso) {
  if (!iso) return '—'
  return new Date(iso).toLocaleString('pt-BR', {
    day: '2-digit', month: '2-digit', year: 'numeric',
    hour: '2-digit', minute: '2-digit'
  })
}

// ── Preview ───────────────────────────────────────────────────
const previewDoc      = ref(null)
const previewOpen     = ref(false)
const previewFaqItens = ref([])

async function abrirPreview (doc) {
  previewDoc.value  = doc
  previewOpen.value = true
  // Carrega itens FAQ para o preview
  const { data } = await supabase
    .from('saas_faq_itens')
    .select('id, pergunta, resposta, ordem')
    .eq('doc_id', doc.id)
    .eq('ativo', true)
    .order('ordem')
  previewFaqItens.value = data || []
}

const previewRelated = computed(() => {
  const ids = previewDoc.value?.docs_relacionados || []
  return docs.value.filter(d => ids.includes(d.id))
})

const previewFaqAbertos = ref({})
function togglePreviewFaq (id) {
  previewFaqAbertos.value[id] = !previewFaqAbertos.value[id]
}

// ── Dialog de Prompt ────────────────────────────────────────────
const promptDlgOpen = ref(false)

// ── Importar JSON ─────────────────────────────────────────────
const jsonFileInputRef = ref(null)

function copiarPrompt () {
  const pre = document.querySelector('.prompt-pre')
  if (!pre) return
  navigator.clipboard.writeText(pre.textContent.trim()).then(() => {
    toast.add({ severity: 'success', summary: 'Prompt copiado!', detail: 'Cole no Claude e anexe o arquivo .vue', life: 2500 })
  })
}

function triggerJsonImport () {
  jsonFileInputRef.value?.click()
}

async function onJsonFileChange (event) {
  const file = event.target.files?.[0]
  if (!file) return
  event.target.value = ''

  try {
    const text = await file.text()
    const json = JSON.parse(text)

    // Valida campos mínimos
    if (!json.titulo && !json.conteudo) {
      toast.add({ severity: 'warn', summary: 'JSON inválido', detail: 'O arquivo não parece ser uma documentação válida.', life: 3500 })
      return
    }

    // Detecta se pagina_path é custom (não existe em PAGE_OPTIONS)
    const isCustom = json.pagina_path && !PAGE_OPTIONS.find(p => p.path === json.pagina_path)

    // Popula form (mesmo padrão do abrirDialog)
    editId.value = null
    form.value = {
      titulo:            json.titulo            || '',
      conteudo:          json.conteudo          || '',
      categoria:         json.categoria         || '',
      exibir_no_faq:     json.exibir_no_faq     ?? false,
      tipo_acesso:       json.tipo_acesso        || 'usuario',
      pagina_path:       isCustom ? '__custom__' : (json.pagina_path || null),
      medias:            Array.isArray(json.medias) ? JSON.parse(JSON.stringify(json.medias)) : [],
      docs_relacionados: Array.isArray(json.docs_relacionados) ? [...json.docs_relacionados] : [],
      ativo:             json.ativo             ?? true,
      ordem:             json.ordem             ?? 0,
      _custom_path:      isCustom ? json.pagina_path : '',
      _faq_itens:        Array.isArray(json._faq_itens)
        ? json._faq_itens.map((item, i) => ({
            id:       null,
            pergunta: item.pergunta || '',
            resposta: item.resposta || '',
            ordem:    item.ordem    ?? i,
            ativo:    item.ativo    ?? true,
            _dirty:   true,
            _novo:    true
          }))
        : []
    }

    activeTab.value = 0
    dlgOpen.value = true

    toast.add({
      severity: 'success',
      summary:  'JSON importado',
      detail:   `"${json.titulo}" carregado. Revise e salve.`,
      life:     3000
    })
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro ao ler JSON', detail: e?.message, life: 4000 })
  }
}

// ── Helpers de exibição ───────────────────────────────────────
function tipoLabel (tipo) {
  return tipo === 'admin' ? 'Somente Admin' : 'Usuários'
}
function tipoSeverity (tipo) {
  return tipo === 'admin' ? 'danger' : 'info'
}
function relatedCount (doc) {
  return doc.docs_relacionados?.length || 0
}
function mediasCount (doc) {
  return Array.isArray(doc.medias) ? doc.medias.filter(m => m.url).length : 0
}
</script>

<template>
  <Toast />
  <ConfirmDialog />

  <!-- Input oculto para importação de JSON -->
  <input
    ref="jsonFileInputRef"
    type="file"
    accept=".json,application/json"
    style="display:none"
    @change="onJsonFileChange"
  />

  <!-- Sentinel -->
  <div class="h-px" />

  <!-- Hero sticky -->
  <div
    class="sticky mx-3 md:mx-4 mb-4 z-20 overflow-hidden rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5"
    :style="{ top: 'var(--layout-sticky-top, 56px)' }"
  >
    <div class="absolute inset-0 pointer-events-none overflow-hidden" aria-hidden="true">
      <div class="absolute rounded-full blur-[70px] w-72 h-72 -top-16 -right-20 bg-blue-400/10" />
      <div class="absolute rounded-full blur-[70px] w-80 h-80 top-10 -left-24 bg-indigo-400/10" />
    </div>
    <div class="relative z-10 flex flex-wrap items-center justify-between gap-3">
      <div class="flex items-center gap-3">
        <div class="w-12 h-12 rounded-md border border-[var(--surface-border)] bg-[var(--surface-ground)] flex items-center justify-center flex-shrink-0">
          <i class="pi pi-question-circle text-xl text-blue-500" />
        </div>
        <div>
          <div class="text-[1rem] font-bold tracking-tight text-[var(--text-color)]">Documentação do Sistema</div>
          <div class="text-[1rem] text-[var(--text-color-secondary)] mt-0.5">Artigos de ajuda exibidos dinamicamente nas páginas.</div>
        </div>
      </div>
      <!-- Desktop actions -->
      <div class="hidden xl:flex items-center gap-2">
        <Button icon="pi pi-refresh" severity="secondary" outlined rounded :loading="loading" @click="load" />
        <Button
          icon="pi pi-upload"
          label="Importar JSON"
          severity="secondary"
          outlined
          class="rounded-full"
          v-tooltip.bottom="'Carrega um arquivo .json gerado pelo assistente'"
          @click="triggerJsonImport"
        />
        <Button
          icon="pi pi-comment"
          label="Prompt"
          severity="secondary"
          outlined
          class="rounded-full"
          v-tooltip.bottom="'Ver instruções para gerar documentação com IA'"
          @click="promptDlgOpen = true"
        />
        <Button icon="pi pi-plus" label="Novo documento" class="rounded-full" @click="abrirDialog()" />
      </div>
      <!-- Mobile actions -->
      <div class="flex xl:hidden items-center gap-2">
        <Button icon="pi pi-refresh" severity="secondary" outlined rounded :loading="loading" @click="load" />
        <Button icon="pi pi-upload" severity="secondary" outlined rounded v-tooltip.bottom="'Importar JSON'" @click="triggerJsonImport" />
        <Button icon="pi pi-comment" severity="secondary" outlined rounded v-tooltip.bottom="'Prompt IA'" @click="promptDlgOpen = true" />
        <Button icon="pi pi-plus" rounded @click="abrirDialog()" />
      </div>
    </div>
  </div>

  <div class="px-3 md:px-4 pb-8 flex flex-col gap-4">

    <!-- ── Cards de saúde ──────────────────────────────────── -->
    <div class="flex flex-wrap gap-2.5">
      <!-- Total -->
      <div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border border-[var(--surface-border)] bg-[var(--surface-ground)] min-w-[110px]">
        <div class="text-[1.35rem] font-bold leading-none text-[var(--text-color)]">{{ totalDocs }}</div>
        <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75">Total de docs</div>
      </div>

      <!-- OK -->
      <div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border min-w-[110px]"
        style="border-color: color-mix(in srgb, #22c55e 25%, transparent); background: color-mix(in srgb, #22c55e 5%, var(--surface-card))">
        <div class="text-[1.35rem] font-bold leading-none text-green-600">{{ docsOk.length }}</div>
        <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75 flex items-center gap-1">
          <i class="pi pi-thumbs-up text-green-500 text-[10px]" />Bem avaliadas
        </div>
      </div>

      <!-- Atenção — clicável para filtrar -->
      <div
        class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border min-w-[110px] cursor-pointer transition-all"
        :style="filtroAtencao
          ? 'border-color: #ef4444; background: color-mix(in srgb, #ef4444 10%, var(--surface-card)); box-shadow: 0 0 0 3px color-mix(in srgb, #ef4444 15%, transparent)'
          : 'border-color: color-mix(in srgb, #ef4444 25%, transparent); background: color-mix(in srgb, #ef4444 5%, var(--surface-card))'"
        v-tooltip.bottom="filtroAtencao ? 'Clique para ver todas' : 'Clique para filtrar'"
        @click="filtroAtencao = !filtroAtencao"
      >
        <div class="text-[1.35rem] font-bold leading-none text-red-500 flex items-center gap-1.5">
          {{ docsAtencao.length }}
          <i v-if="docsAtencao.length" class="pi pi-exclamation-triangle text-[1rem] text-red-400" />
        </div>
        <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75 flex items-center gap-1">
          <i class="pi pi-thumbs-down text-red-400 text-[10px]" />Precisam de atenção
        </div>
      </div>

      <!-- Sem dados -->
      <div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border border-[var(--surface-border)] bg-[var(--surface-ground)] min-w-[110px]">
        <div class="text-[1.35rem] font-bold leading-none text-[var(--text-color-secondary)]">{{ docsSemDados.length }}</div>
        <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-60">Sem votos</div>
      </div>

      <!-- Mais útil -->
      <div v-if="docMaisUtil" class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border flex-1 min-w-0"
        style="border-color: color-mix(in srgb, var(--primary-color) 30%, transparent); background: color-mix(in srgb, var(--primary-color) 5%, var(--surface-card))">
        <div class="text-[1rem] font-semibold truncate text-[var(--primary-color)]">{{ docMaisUtil.titulo }}</div>
        <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75 flex items-center gap-1">
          <i class="pi pi-star text-amber-400 text-[10px]" />Mais útil
          <span class="ml-1 opacity-60">({{ docMaisUtil.votos_util }} 👍)</span>
        </div>
      </div>
    </div>

    <!-- Banner de alerta quando há docs com problema -->
    <div v-if="docsAtencao.length && !filtroAtencao"
      class="flex items-center gap-2.5 px-3.5 py-2.5 rounded-md border text-[1rem] text-[var(--text-color)]"
      style="background: color-mix(in srgb, #f59e0b 8%, var(--surface-card)); border-color: color-mix(in srgb, #f59e0b 35%, transparent)"
    >
      <i class="pi pi-exclamation-triangle text-amber-500 shrink-0" />
      <span>
        <strong>{{ docsAtencao.length }} documento{{ docsAtencao.length > 1 ? 's' : '' }}</strong>
        {{ docsAtencao.length > 1 ? 'estão recebendo' : 'está recebendo' }} mais de 30% de votos negativos.
        <button class="underline text-[var(--primary-color)] ml-1" @click="filtroAtencao = true">Ver agora</button>
      </span>
    </div>

    <!-- ── Tabela ──────────────────────────────────────────── -->
    <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] overflow-hidden">
      <DataTable
        :value="docsFiltrados"
        :loading="loading"
        v-model:filters="filters"
        :globalFilterFields="['titulo', 'pagina_path', 'categoria']"
        filterDisplay="menu"
        paginator
        :rows="10"
        :rowsPerPageOptions="[5, 10, 25, 50]"
        paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
        dataKey="id"
        removableSort
        class=""
        :emptyMessage="loading ? ' ' : filtroAtencao ? 'Nenhum documento com problema.' : 'Nenhum documento encontrado.'"
        :rowClass="(data) => saudeDoc(data) === 'atencao' ? 'row-atencao' : ''"
      >
        <template #header>
          <div class="flex items-center justify-between px-1 py-1 gap-2">
            <div v-if="filtroAtencao" class="flex items-center gap-2">
              <span class="text-[1rem] font-semibold text-red-500 flex items-center gap-1">
                <i class="pi pi-filter" />Filtrando: precisam de atenção
              </span>
              <button class="text-[1rem] text-[var(--text-color-secondary)] underline" @click="filtroAtencao = false">
                Limpar
              </button>
            </div>
            <div v-else class="flex-1" />
            <IconField>
              <InputIcon class="pi pi-search" />
              <InputText v-model="filters['global'].value" placeholder="Buscar por título ou página…" class="w-72" />
            </IconField>
          </div>
        </template>

        <!-- Título + badges -->
        <Column field="titulo" header="Documento" sortable style="min-width: 220px">
          <template #body="{ data }">
            <div class="flex flex-col gap-1">
              <div class="flex items-center gap-2 flex-wrap">
                <span class="font-semibold text-[1rem]">{{ data.titulo }}</span>
                <Tag :value="tipoLabel(data.tipo_acesso)" :severity="tipoSeverity(data.tipo_acesso)" class="text-[1rem]" />
                <Tag v-if="!data.ativo" value="Inativo" severity="secondary" class="text-[1rem]" />
                <span v-if="data.exibir_no_faq" class="inline-flex items-center text-[1rem] font-bold px-1.5 py-px rounded border" style="background: color-mix(in srgb, var(--primary-color) 15%, transparent); color: var(--primary-color); border-color: color-mix(in srgb, var(--primary-color) 30%, transparent); letter-spacing: 0.05em">FAQ</span>
              </div>
              <div class="flex items-center gap-3 text-[1rem] text-[var(--text-color-secondary)] opacity-70">
                <span v-if="data.categoria"><i class="pi pi-tag mr-1" />{{ data.categoria }}</span>
                <span v-if="relatedCount(data)"><i class="pi pi-link mr-1" />{{ relatedCount(data) }}</span>
                <span v-if="mediasCount(data)"><i class="pi pi-image mr-1" />{{ mediasCount(data) }}</span>
              </div>
            </div>
          </template>
        </Column>

        <!-- Página -->
        <Column field="pagina_path" header="Página" sortable style="min-width: 160px">
          <template #body="{ data }">
            <span class="text-[1rem] font-mono text-[var(--text-color-secondary)]">{{ data.pagina_path }}</span>
          </template>
        </Column>

        <!-- Saúde / Votos -->
        <Column header="Votos" style="min-width: 130px; white-space: nowrap">
          <template #body="{ data }">
            <div class="flex items-center gap-2">
              <!-- Sem votos suficientes -->
              <span v-if="saudeDoc(data) === 'sem_dados'" class="text-[1rem] text-[var(--text-color-secondary)] opacity-40 italic">
                sem dados
              </span>
              <template v-else>
                <!-- Indicador de saúde -->
                <div
                  class="w-2 h-2 rounded-full shrink-0"
                  :class="saudeDoc(data) === 'atencao' ? 'bg-red-500 animate-pulse' : 'bg-green-500'"
                  v-tooltip.top="saudeDoc(data) === 'atencao'
                    ? `${pctNegativo(data)}% negativos — precisa de atenção`
                    : `${pctNegativo(data)}% negativos — OK`"
                />
                <!-- Contadores -->
                <div class="flex items-center gap-1.5 text-[1rem]">
                  <span class="flex items-center gap-0.5 text-green-600">
                    <i class="pi pi-thumbs-up text-[10px]" />{{ data.votos_util || 0 }}
                  </span>
                  <span class="text-[var(--surface-border)]">·</span>
                  <span class="flex items-center gap-0.5 text-red-500">
                    <i class="pi pi-thumbs-down text-[10px]" />{{ data.votos_nao_util || 0 }}
                  </span>
                </div>
                <!-- % negativo para docs em atenção -->
                <span v-if="saudeDoc(data) === 'atencao'" class="text-[1rem] text-red-400 font-semibold">
                  {{ pctNegativo(data) }}%
                </span>
              </template>
            </div>
          </template>
        </Column>

        <!-- Modificado em -->
        <Column field="updated_at" header="Modificado em" sortable style="min-width: 130px; white-space: nowrap">
          <template #body="{ data }">
            <span class="text-[1rem] text-[var(--text-color-secondary)]">{{ fmtDate(data.updated_at) }}</span>
          </template>
        </Column>

        <!-- Ações -->
        <Column header="" style="width: 110px; text-align: right">
          <template #body="{ data }">
            <div class="flex items-center justify-end gap-1">
              <Button icon="pi pi-eye"    text rounded size="small" severity="info"      v-tooltip.top="'Visualizar'" @click="abrirPreview(data)" />
              <Button icon="pi pi-pencil" text rounded size="small" severity="secondary" v-tooltip.top="'Editar'"      @click="abrirDialog(data)" />
              <Button icon="pi pi-trash"  text rounded size="small" severity="danger"    v-tooltip.top="'Excluir'"     @click="excluir(data)" />
            </div>
          </template>
        </Column>
      </DataTable>
    </div>

  </div><!-- /px-3 content wrapper -->

  <!-- ══ Dialog de preview ══════════════════════════════════ -->
  <Dialog
    v-model:visible="previewOpen"
    modal
    :draggable="false"
    :style="{ width: '520px', maxWidth: '95vw' }"
    @hide="previewFaqAbertos = {}"
  >
    <template #header>
      <div class="flex items-center gap-2">
        <i class="pi pi-question-circle text-blue-500" />
        <span class="font-semibold">{{ previewDoc?.titulo }}</span>
        <Tag :value="tipoLabel(previewDoc?.tipo_acesso)" :severity="tipoSeverity(previewDoc?.tipo_acesso)" class="text-[1rem] ml-1" />
        <span v-if="previewDoc?.exibir_no_faq" class="inline-flex items-center text-[1rem] font-bold px-1.5 py-px rounded border ml-1" style="background: color-mix(in srgb, var(--primary-color) 15%, transparent); color: var(--primary-color); border-color: color-mix(in srgb, var(--primary-color) 30%, transparent); letter-spacing: 0.05em">FAQ</span>
      </div>
    </template>

    <div v-if="previewDoc" class="flex flex-col gap-4 py-1">
      <div class="text-[1rem] font-mono text-[var(--text-color-secondary)] bg-[var(--surface-ground)] rounded-md px-3 py-2">
        <i class="pi pi-map-marker mr-1 opacity-60" />{{ previewDoc.pagina_path }}
        <span v-if="previewDoc.categoria" class="ml-2 opacity-60">· {{ previewDoc.categoria }}</span>
      </div>

      <div v-if="previewDoc.conteudo" class="text-[1rem] leading-relaxed text-[var(--text-color-secondary)] ql-content" v-html="previewDoc.conteudo" />

      <!-- Mídias -->
      <template v-if="previewDoc.medias?.length">
        <div v-for="(m, idx) in previewDoc.medias.filter(m => m.url)" :key="idx">
          <img v-if="m.tipo === 'imagem'" :src="m.url" class="w-full rounded-md border border-[var(--surface-border)]" :alt="previewDoc.titulo" />
          <div v-else-if="m.tipo === 'video'" class="relative w-full rounded-md overflow-hidden border border-[var(--surface-border)]" style="padding-top: 56.25%">
            <iframe :src="m.url" frameborder="0" allowfullscreen class="absolute inset-0 w-full h-full" />
          </div>
        </div>
      </template>

      <!-- FAQ itens preview -->
      <div v-if="previewFaqItens.length" class="border-t border-[var(--surface-border)] pt-3">
        <div class="text-[1rem] font-bold uppercase tracking-wider text-[var(--text-color-secondary)] mb-2">
          <i class="pi pi-comments mr-1" />Perguntas frequentes
        </div>
        <div class="flex flex-col gap-1">
          <div
            v-for="item in previewFaqItens"
            :key="item.id"
            class="rounded-md overflow-hidden mb-px border bg-[var(--surface-ground)]"
            :style="previewFaqAbertos[item.id] ? 'border-color: color-mix(in srgb, var(--primary-color) 30%, transparent)' : 'border-color: var(--surface-border)'"
          >
            <button
              class="w-full flex items-center justify-between gap-2 px-3 py-2 text-[1rem] font-medium bg-transparent border-none cursor-pointer text-left text-[var(--text-color)]"
              @click="togglePreviewFaq(item.id)"
            >
              <span>{{ item.pergunta }}</span>
              <i class="pi opacity-40 shrink-0" :class="previewFaqAbertos[item.id] ? 'pi-chevron-up' : 'pi-chevron-down'" />
            </button>
            <div v-if="previewFaqAbertos[item.id] && item.resposta" class="px-3 pb-2 text-[1rem] text-[var(--text-color-secondary)] leading-relaxed ql-content" v-html="item.resposta" />
          </div>
        </div>
      </div>

      <!-- Veja também -->
      <div v-if="previewRelated.length" class="border-t border-[var(--surface-border)] pt-3">
        <div class="text-[1rem] font-bold uppercase tracking-wider text-[var(--text-color-secondary)] mb-2">
          <i class="pi pi-link mr-1" />Veja também
        </div>
        <div class="flex flex-col gap-1">
          <div v-for="rel in previewRelated" :key="rel.id" class="flex items-center gap-2 px-3 py-2 rounded-md bg-[var(--surface-ground)] text-[1rem] text-[var(--primary-color)]">
            <i class="pi pi-arrow-right" />
            <span class="font-medium">{{ rel.titulo }}</span>
            <span class="text-[1rem] text-[var(--text-color-secondary)] font-mono ml-auto">{{ rel.pagina_path }}</span>
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <Button label="Fechar"  severity="secondary" outlined @click="previewOpen = false" />
      <Button label="Editar"  icon="pi pi-pencil"  @click="previewOpen = false; abrirDialog(previewDoc)" />
    </template>
  </Dialog>

  <!-- ══ Dialog de criação / edição ═════════════════════════ -->
  <Dialog
    v-model:visible="dlgOpen"
    modal
    :draggable="false"
    :header="editId ? 'Editar documento' : 'Novo documento'"
    :style="{ width: '680px', maxWidth: '95vw' }"
  >
    <!-- Tabs de navegação -->
    <div class="flex gap-0 border-b border-[var(--surface-border)] -mx-6 px-6">
      <button
        v-for="(tab, i) in ['Conteúdo', 'Perguntas FAQ', 'Mídias', 'Configurações']"
        :key="i"
        class="flex items-center px-4 py-2.5 text-[1rem] font-medium bg-transparent border-none border-b-2 -mb-px cursor-pointer transition-colors whitespace-nowrap"
        :class="activeTab === i
          ? 'text-[var(--primary-color)] border-b-[var(--primary-color)]'
          : 'text-[var(--text-color-secondary)] border-b-transparent hover:text-[var(--text-color)]'"
        :style="activeTab === i ? 'border-bottom-color: var(--primary-color)' : 'border-bottom-color: transparent'"
        @click="activeTab = i"
      >
        <i class="mr-1.5" :class="['pi', i === 0 ? 'pi-align-left' : i === 1 ? 'pi-comments' : i === 2 ? 'pi-image' : 'pi-cog']" />
        {{ tab }}
        <span v-if="i === 1 && form._faq_itens.length" class="inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 ml-1.5 rounded-full bg-[var(--primary-color)] text-white text-[1rem] font-bold">{{ form._faq_itens.length }}</span>
      </button>
    </div>

    <div class="flex flex-col gap-5 pt-4">

      <!-- ── Aba 0: Conteúdo ─────────────────────────────────── -->
      <template v-if="activeTab === 0">
        <div>
          <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Título *</label>
          <InputText v-model="form.titulo" class="w-full mt-1" placeholder="Ex.: Como fazer login, Como trocar a senha…" />
        </div>
        <div>
          <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Página de exibição *</label>
          <Select
            v-model="form.pagina_path"
            :options="pageSelectOptions"
            optionLabel="label"
            optionValue="path"
            class="w-full mt-1"
            filter
            filterPlaceholder="Buscar página…"
            placeholder="Selecione a página…"
          >
            <template #option="{ option }">
              <div class="flex items-center justify-between gap-2 w-full min-w-0">
                <span class="truncate text-[1rem]">{{ option.label }}</span>
                <span
                  v-if="docsCountByPath.get(option.path)"
                  class="shrink-0 inline-flex items-center gap-1 text-[0.6rem] font-bold px-1.5 py-0.5 rounded-full bg-[var(--primary-color)] text-white opacity-80"
                >
                  <i class="pi pi-file" style="font-size:0.6rem" />
                  {{ docsCountByPath.get(option.path) }} doc{{ docsCountByPath.get(option.path) > 1 ? 's' : '' }}
                </span>
              </div>
            </template>
          </Select>
          <InputText v-if="isCustomPath" v-model="form._custom_path" class="w-full mt-2" placeholder="/caminho/da/pagina" />
          <div v-if="resolvedPath" class="text-[1rem] font-mono text-[var(--text-color-secondary)] mt-1 opacity-70">
            path: {{ resolvedPath }}
          </div>
        </div>
        <div>
          <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Conteúdo</label>
          <Editor v-model="form.conteudo" class="mt-1" editorStyle="height: 220px" />
        </div>
        <div>
          <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Docs relacionados <span class="opacity-50 ml-1">(exibidos no rodapé como "Veja também")</span></label>
          <MultiSelect
            v-model="form.docs_relacionados"
            :options="docsRelOptions"
            optionLabel="label"
            optionValue="value"
            class="w-full mt-1"
            filter
            display="chip"
            placeholder="Selecione docs relacionados…"
            :maxSelectedLabels="4"
            emptyFilterMessage="Nenhum doc encontrado"
            emptyMessage="Nenhum doc cadastrado ainda"
          />
        </div>
      </template>

      <!-- ── Aba 1: Perguntas FAQ ────────────────────────────── -->
      <template v-if="activeTab === 1">
        <!-- Habilitar FAQ -->
        <div class="flex items-center justify-between rounded-md border border-[var(--surface-border)] bg-[var(--surface-ground)] px-4 py-3">
          <div>
            <div class="text-[1rem] font-medium">Exibir no portal FAQ</div>
            <div class="text-[1rem] text-[var(--text-color-secondary)] mt-0.5">
              Quando ativo, este documento e suas perguntas aparecem na página de FAQ do sistema.
            </div>
          </div>
          <ToggleSwitch v-model="form.exibir_no_faq" />
        </div>

        <!-- Categoria -->
        <div>
          <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Categoria <span class="opacity-50 ml-1">(agrupa no portal FAQ)</span></label>
          <AutoComplete
            v-model="form.categoria"
            :suggestions="categorias.filter(c => !form.categoria || c.toLowerCase().includes(String(form.categoria).toLowerCase()))"
            class="w-full mt-1"
            placeholder="Ex.: Conta, Agenda, Pagamentos…"
            @complete="() => {}"
          />
          <div v-if="categorias.length" class="flex flex-wrap gap-1 mt-2">
            <button
              v-for="cat in categorias"
              :key="cat"
              class="inline-flex items-center text-[1rem] font-medium px-2 py-0.5 rounded-full border cursor-pointer transition-all"
              :class="form.categoria === cat
                ? 'text-[var(--primary-color)] border-[var(--primary-color)]'
                : 'text-[var(--text-color-secondary)] border-[var(--surface-border)] bg-[var(--surface-ground)] hover:border-[var(--primary-color)] hover:text-[var(--primary-color)]'"
              :style="form.categoria === cat ? 'background: color-mix(in srgb, var(--primary-color) 12%, transparent); border-color: color-mix(in srgb, var(--primary-color) 35%, transparent)' : ''"
              @click="form.categoria = form.categoria === cat ? '' : cat"
            >
              {{ cat }}
            </button>
          </div>
        </div>

        <!-- Lista de itens FAQ -->
        <div>
          <div class="flex items-center justify-between mb-3">
            <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Perguntas e respostas</label>
            <Button icon="pi pi-plus" label="Adicionar pergunta" text size="small" @click="addFaqItem" />
          </div>

          <div v-if="faqLoading" class="flex justify-center py-6">
            <i class="pi pi-spinner pi-spin opacity-40" />
          </div>

          <div v-else-if="!form._faq_itens.length" class="text-[1rem] text-[var(--text-color-secondary)] italic text-center py-6 border border-dashed border-[var(--surface-border)] rounded-md">
            Nenhuma pergunta adicionada ainda.<br />
            <button class="text-[var(--primary-color)] mt-1 underline text-[1rem]" @click="addFaqItem">Adicionar a primeira</button>
          </div>

          <div v-else class="flex flex-col gap-3">
            <div
              v-for="(item, idx) in form._faq_itens"
              :key="idx"
              class="p-3.5 border border-[var(--surface-border)] rounded-md bg-[var(--surface-ground)]"
            >
              <div class="flex items-center justify-between mb-2">
                <span class="text-[1rem] font-semibold text-[var(--text-color-secondary)] opacity-60">Pergunta {{ idx + 1 }}</span>
                <div class="flex items-center gap-1">
                  <ToggleSwitch v-model="item.ativo" v-tooltip.top="'Ativo'" />
                  <Button icon="pi pi-trash" text rounded size="small" severity="danger" @click="removeFaqItem(idx)" />
                </div>
              </div>
              <InputText
                v-model="item.pergunta"
                class="w-full mb-2"
                placeholder="Ex.: Como redefinir minha senha?"
              />
              <Editor
                v-model="item.resposta"
                editorStyle="height: 120px"
              />
            </div>
          </div>
        </div>
      </template>

      <!-- ── Aba 2: Mídias ──────────────────────────────────── -->
      <template v-if="activeTab === 2">
        <div>
          <div class="flex items-center justify-between mb-2">
            <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Imagens e vídeos</label>
            <Button icon="pi pi-plus" label="Adicionar" text size="small" @click="addMedia" />
          </div>

          <div v-if="!form.medias.length" class="text-[1rem] text-[var(--text-color-secondary)] italic">
            Nenhuma mídia adicionada.
          </div>

          <div v-for="(m, idx) in form.medias" :key="idx" class="flex items-center gap-2 mb-2 p-2 rounded-md border border-[var(--surface-border)] bg-[var(--surface-ground)]">
            <Select
              v-model="m.tipo"
              :options="[{ label: 'Imagem', value: 'imagem' }, { label: 'Vídeo (embed)', value: 'video' }]"
              optionLabel="label"
              optionValue="value"
              class="w-36 shrink-0"
            />
            <template v-if="m.tipo === 'imagem'">
              <input
                type="file"
                accept="image/*"
                style="display: none"
                :ref="el => { if (el) fileInputRefs[idx] = el }"
                @change="uploadImagem(idx, $event)"
              />
              <div v-if="!m.url" class="flex-1">
                <Button icon="pi pi-upload" label="Enviar imagem" severity="secondary" outlined :loading="uploadingIdx.has(idx)" class="w-full" @click="triggerUpload(idx)" />
              </div>
              <div v-else class="flex items-center gap-2 flex-1 min-w-0">
                <img :src="m.url" class="w-14 h-14 object-cover rounded-md border border-[var(--surface-border)] flex-shrink-0" :alt="`Imagem ${idx + 1}`" />
                <div class="flex flex-col gap-1 flex-1 min-w-0">
                  <span class="text-[1rem] font-mono truncate text-[var(--text-color-secondary)]">{{ m.url }}</span>
                  <Button icon="pi pi-refresh" label="Trocar imagem" text size="small" severity="secondary" :loading="uploadingIdx.has(idx)" @click="triggerUpload(idx)" />
                </div>
              </div>
            </template>
            <InputText v-else v-model="m.url" class="flex-1" placeholder="https://www.youtube.com/embed/ID" />
            <Button icon="pi pi-trash" text rounded size="small" severity="danger" @click="removeMedia(idx)" />
          </div>
        </div>
      </template>

      <!-- ── Aba 3: Configurações ───────────────────────────── -->
      <template v-if="activeTab === 3">
        <div>
          <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Visibilidade</label>
          <div class="mt-1">
            <SelectButton v-model="form.tipo_acesso" :options="tipoAcessoOptions" optionLabel="label" optionValue="value" />
          </div>
        </div>
        <div class="flex items-end gap-4">
          <div class="flex-1">
            <label class="text-[1rem] text-[var(--text-color-secondary)] font-medium">Ordem de exibição</label>
            <InputNumber v-model="form.ordem" class="w-full mt-1" :min="0" />
          </div>
          <div class="flex items-center gap-2 pb-1">
            <ToggleSwitch v-model="form.ativo" inputId="doc-ativo" />
            <label for="doc-ativo" class="text-[1rem] cursor-pointer select-none">Ativo</label>
          </div>
        </div>
      </template>

    </div>

    <template #footer>
      <Button label="Cancelar" severity="secondary" outlined @click="dlgOpen = false" />
      <Button
        :label="editId ? 'Salvar alterações' : 'Criar documento'"
        icon="pi pi-check"
        :disabled="!formValid"
        :loading="saving"
        @click="salvar"
      />
    </template>
  </Dialog>
  <!-- ══ Dialog de Prompt IA ════════════════════════════════ -->
  <Dialog
    v-model:visible="promptDlgOpen"
    modal
    :draggable="false"
    header="Gerar documentação com IA"
    :style="{ width: '680px', maxWidth: '95vw' }"
    pt:mask:class="backdrop-blur-xs"
  >
    <div class="flex flex-col gap-4">

      <!-- Instrução humana -->
      <div class="flex items-start gap-3 rounded-[6px] border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
        <i class="pi pi-info-circle text-blue-500 text-lg shrink-0 mt-0.5" />
        <div class="text-[1rem] text-[var(--text-color-secondary)] leading-relaxed">
          Usando o <strong class="text-[var(--text-color)]">Claude</strong>, envie o arquivo <code class="text-[1rem] bg-[var(--surface-border)] px-1.5 py-0.5 rounded">.vue</code> da página que deseja documentar.
          O Claude irá analisar os componentes, identificar os <code class="text-[1rem] bg-[var(--surface-border)] px-1.5 py-0.5 rounded">id</code>s dos elementos,
          reproduzir visualmente os cards e seções dentro do conteúdo, criar as perguntas FAQ, definir a rota correta de exibição
          e retornar um arquivo <code class="text-[1rem] bg-[var(--surface-border)] px-1.5 py-0.5 rounded">.json</code> pronto para importar aqui.
        </div>
      </div>

      <!-- Prompt copiável -->
      <div class="relative">
        <div class="flex items-center justify-between mb-2">
          <span class="text-[1rem] font-bold uppercase tracking-wider text-[var(--text-color-secondary)] opacity-60">
            <i class="pi pi-clipboard mr-1" />Prompt para o Claude
          </span>
          <Button
            icon="pi pi-copy"
            label="Copiar"
            size="small"
            text
            class="rounded-full"
            @click="copiarPrompt"
          />
        </div>
        <pre class="prompt-pre">Você é um especialista em documentação de produto SaaS voltado para psicólogos e terapeutas.

Vou te enviar o código-fonte de uma página Vue.js do sistema. Sua tarefa é:

1. ANALISAR o código completo — componentes, props, lógica, rotas, dados carregados do Supabase e regras de negócio visíveis
2. IDENTIFICAR todos os elementos com id= e quais não têm (sugerindo os que deveriam ter para o sistema de highlight da ajuda)
3. REPRODUZIR visualmente no campo "conteudo" os cards, timelines, tabelas e seções mais importantes usando HTML inline com estilos CSS, exatamente como foi feito nos exemplos abaixo — para que o usuário veja o elemento real dentro da documentação
4. CRIAR links de highlight usando o padrão: &lt;a data-highlight="id-do-elemento" data-route="/rota-da-pagina" href="#"&gt;Ver na tela&lt;/a&gt;
5. DEFINIR a rota correta no campo "pagina_path" baseada nos comentários, nome do componente e router-links encontrados no código
6. GERAR entre 8 e 12 perguntas FAQ reais que um terapeuta iniciante faria sobre essa tela
7. RETORNAR um único arquivo .json com a estrutura abaixo, pronto para importar no sistema

ESTRUTURA DO JSON (siga exatamente):
{
  "titulo": "string — título claro e objetivo",
  "conteudo": "string — HTML rico com &lt;h2&gt;, &lt;h3&gt;, &lt;h4&gt;, &lt;p&gt;, &lt;ul&gt;, &lt;li&gt;, &lt;strong&gt;, cards reproduzidos em HTML inline e links data-highlight",
  "categoria": "string — ex: Agenda, Pacientes, Financeiro, Configurações",
  "exibir_no_faq": true,
  "tipo_acesso": "usuario",
  "pagina_path": "string — rota exata ex: /therapist, /therapist/agenda",
  "ordem": 1,
  "ativo": true,
  "medias": [{ "tipo": "imagem", "url": "" }],
  "_faq_itens": [
    {
      "pergunta": "string — pergunta real de um usuário iniciante",
      "resposta": "string — resposta clara e direta",
      "ordem": 0,
      "ativo": true
    }
  ]
}

REGRAS OBRIGATÓRIAS:
- "conteudo" deve ser HTML válido em português do Brasil
- Reproduza visualmente pelo menos 2 elementos da tela (cards, timeline, etc.) usando HTML+CSS inline
- Explique TODOS os botões, campos, filtros, modais e fluxos visíveis no código
- Se houver regras de negócio (ex: item padrão não pode ser excluído, campo obrigatório), documente
- Para cada elemento importante que tiver id= no código, crie um link data-highlight correspondente
- Se um elemento importante NÃO tiver id=, mencione que o id precisa ser adicionado ao componente
- Links data-highlight funcionam tanto no "conteudo" quanto nas "respostas" do _faq_itens — use em ambos sempre que referenciar um elemento da tela
- Nas respostas do FAQ, quando mencionar um card ou seção específica, sempre inclua o link data-highlight correspondente e, se houver uma rota dedicada para aquela funcionalidade (ex: $router.push encontrado no código), inclua também o caminho em &lt;code&gt; ou como texto
- "medias" deve ter 1 item vazio como placeholder
- Não invente funcionalidades que não existem no código

Agora analise o arquivo .vue anexo e gere o JSON completo:</pre>
      </div>

    </div>

    <template #footer>
      <div class="flex items-center justify-between gap-2">
        <span class="text-[1rem] text-[var(--text-color-secondary)] opacity-60">
          <i class="pi pi-lightbulb mr-1" />Cole o prompt no Claude e anexe o arquivo .vue da página
        </span>
        <div class="flex gap-2">
          <Button label="Fechar" severity="secondary" outlined class="rounded-full" @click="promptDlgOpen = false" />
          <Button label="Copiar prompt" icon="pi pi-copy" class="rounded-full" @click="copiarPrompt" />
        </div>
      </div>
    </template>
  </Dialog>

</template>

<style scoped>
.prompt-pre {
  font-family: var(--font-family, monospace);
  font-size: 0.75rem;
  line-height: 1.65;
  color: var(--text-color);
  background: var(--surface-ground);
  border: 1px solid var(--surface-border);
  border-radius: 6px;
  padding: 1rem;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 380px;
  overflow-y: auto;
  margin: 0;
}

:deep(.row-atencao td) {
  background: color-mix(in srgb, #ef4444 4%, var(--surface-card)) !important;
}
:deep(.row-atencao:hover td) {
  background: color-mix(in srgb, #ef4444 8%, var(--surface-card)) !important;
}
</style>