<script setup>
import { ref, computed, onMounted, watch, nextTick, onBeforeUnmount } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useRoleGuard } from '@/composables/useRoleGuard'

import { useToast } from 'primevue/usetoast'
import { useConfirm } from 'primevue/useconfirm'

import { supabase } from '@/lib/supabase/client'
import { useTenantStore } from '@/stores/tenantStore'

const { canSee } = useRoleGuard()

const route = useRoute()
const router = useRouter()
const toast = useToast()
const confirm = useConfirm()

const tenantStore = useTenantStore()

/**
 * ✅ NOTAS IMPORTANTES DO AJUSTE
 * - Corrige o 404 (admin usa /pacientes..., therapist usa /patients...).
 * - Depois de criar (insert), faz upload do avatar usando o ID recém-criado.
 * - Se bucket não for público, troca para signed URL automaticamente (fallback).
 */

// ------------------------------------------------------
// Tenant helpers
// ------------------------------------------------------
async function getCurrentTenantId () {
  return tenantStore.tenantId || tenantStore.currentTenantId || tenantStore.tenant?.id
}

async function getCurrentMemberId (tenantId) {
  const { data: authData, error: authError } = await supabase.auth.getUser()
  if (authError) throw authError
  const uid = authData?.user?.id
  if (!uid) throw new Error('Sessão inválida.')

  const { data, error } = await supabase
    .from('tenant_members')
    .select('id')
    .eq('tenant_id', tenantId)
    .eq('user_id', uid)
    .eq('status', 'active')
    .single()

  if (error) throw error
  if (!data?.id) throw new Error('Responsible member not found')
  return data.id
}

// ------------------------------------------------------
// Accordion: abre 1 por vez + scroll
// ------------------------------------------------------
const activeValue = ref('0')
const panelHeaderRefs = ref([])

function setPanelHeaderRef (el, idx) {
  if (!el) return
  panelHeaderRefs.value[idx] = el
}

async function openPanel (i) {
  activeValue.value = String(i)
  await nextTick()

  const headerRef = panelHeaderRefs.value?.[i]
  const el = headerRef?.$el ?? headerRef
  if (el && typeof el.scrollIntoView === 'function') {
    el.scrollIntoView({ behavior: 'smooth', block: 'start' })
  }
}

// ------------------------------------------------------
// Menu responsivo (>=1200: botões | <1200: popover no MAIN)
// ------------------------------------------------------
const navItems = [
  { value: '0', label: 'Informações pessoais', icon: 'pi pi-user' },
  { value: '1', label: 'Endereço', icon: 'pi pi-map-marker' },
  { value: '2', label: 'Dados adicionais', icon: 'pi pi-briefcase' },
  { value: '3', label: 'Responsável', icon: 'pi pi-users' },
  { value: '4', label: 'Anotações internas', icon: 'pi pi-lock' }
]

const navPopover = ref(null)
function toggleNav (event) { navPopover.value?.toggle(event) }
function selectNav (item) { openPanel(Number(item.value)); navPopover.value?.hide() }
const selectedNav = computed(() => navItems.find(i => i.value === activeValue.value) || null)

// Responsivo < 1200px
const isCompact = ref(false)
let mql = null
let mqlHandler = null

function syncCompact () { isCompact.value = !!mql?.matches }

onMounted(() => {
  mql = window.matchMedia('(max-width: 1199px)')
  syncCompact()
  mqlHandler = () => syncCompact()
  if (mql.addEventListener) mql.addEventListener('change', mqlHandler)
  else mql.addListener(mqlHandler)
})

onBeforeUnmount(() => {
  if (!mql || !mqlHandler) return
  if (mql.removeEventListener) mql.removeEventListener('change', mqlHandler)
  else mql.removeListener(mqlHandler)
})

// ------------------------------------------------------
// Route helpers
// ------------------------------------------------------
const patientId = computed(() => String(route.params?.id || '').trim() || null)
const isEdit = computed(() => !!patientId.value)

// ------------------------------------------------------
// ✅ FIX 404: base por área + rotas reais (admin: /pacientes | therapist: /patients)
// ------------------------------------------------------
function getAreaKey () {
  const seg = String(route.path || '').split('/').filter(Boolean)[0] || 'admin'
  return seg === 'therapist' ? 'therapist' : 'admin'
}

function getPatientsRoutes () {
  const area = getAreaKey()

  if (area === 'therapist') {
    return {
      listName: 'therapist-patients',
      editName: 'therapist-patients-edit',
      listPath: '/therapist/patients',
      editPath: (id) => `/therapist/patients/cadastro/${id}`
    }
  }

  return {
    listName: 'admin-pacientes',
    editName: 'admin-pacientes-cadastro-edit',
    listPath: '/admin/pacientes',
    editPath: (id) => `/admin/pacientes/cadastro/${id}`
  }
}

async function safePush (toNameObj, fallbackPath) {
  try {
    const r = router.resolve(toNameObj)
    if (r?.matched?.length) return router.push(toNameObj)
  } catch (_) {}
  return router.push(fallbackPath)
}

function goBack () {
  const { listName, listPath } = getPatientsRoutes()
  if (window.history.length > 1) router.back()
  else safePush({ name: listName }, listPath)
}

// ------------------------------------------------------
// Avatar state (TEM que existir no setup)
// ------------------------------------------------------
const avatarFile = ref(null)
const avatarPreviewUrl = ref('')
const avatarUploading = ref(false)

const AVATAR_BUCKET = 'avatars'

function isImageFile (file) {
  return !!file && typeof file.type === 'string' && file.type.startsWith('image/')
}

function safeExtFromFile (file) {
  const name = String(file?.name || '')
  const ext = name.includes('.') ? name.split('.').pop() : ''
  const clean = String(ext || '').toLowerCase().replace(/[^a-z0-9]/g, '')
  return clean || 'png'
}

function revokePreview () {
  if (avatarPreviewUrl.value && avatarPreviewUrl.value.startsWith('blob:')) {
    try { URL.revokeObjectURL(avatarPreviewUrl.value) } catch (_) {}
  }
  avatarPreviewUrl.value = ''
}

function onAvatarPicked (ev) {
  const file = ev?.target?.files?.[0] || null

  avatarFile.value = null
  revokePreview()

  if (!file) return
  if (!isImageFile(file)) {
    toast.add({ severity: 'warn', summary: 'Avatar', detail: 'Selecione um arquivo de imagem (PNG/JPG/WebP).', life: 3000 })
    return
  }

  avatarFile.value = file
  avatarPreviewUrl.value = URL.createObjectURL(file)
  toast.add({ severity: 'info', summary: 'Avatar', detail: 'Preview carregado. Clique em “Salvar” para enviar.', life: 2500 })
}

// ✅ Gera URL pública OU signed URL (se o bucket for privado)
async function getReadableAvatarUrl (path) {
  // tenta público primeiro
  try {
    const { data: pub } = supabase.storage.from(AVATAR_BUCKET).getPublicUrl(path)
    const publicUrl = pub?.publicUrl || null
    if (publicUrl) return publicUrl
  } catch (_) {}

  // fallback: signed (bucket privado)
  const { data, error } = await supabase.storage
    .from(AVATAR_BUCKET)
    .createSignedUrl(path, 60 * 60 * 24 * 7) // 7 dias
  if (error) throw error
  if (!data?.signedUrl) throw new Error('Não consegui gerar signed URL do avatar.')
  return data.signedUrl
}

async function uploadAvatarToStorage ({ ownerId, patientId, file }) {
  if (!ownerId) throw new Error('ownerId ausente.')
  if (!patientId) throw new Error('patientId ausente.')
  if (!file) throw new Error('Arquivo de avatar ausente.')
  if (!isImageFile(file)) throw new Error('Selecione um arquivo de imagem (PNG/JPG/WebP).')

  const maxBytes = 3 * 1024 * 1024
  if (file.size > maxBytes) throw new Error('Imagem muito grande. Use até 3MB.')

  const ext = safeExtFromFile(file)
  const path = `owners/${ownerId}/patients/${patientId}/avatar.${ext}`

  const { error: upErr } = await supabase.storage
    .from(AVATAR_BUCKET)
    .upload(path, file, {
      upsert: true,
      cacheControl: '3600',
      contentType: file.type || 'image/*'
    })

  if (upErr) throw upErr

  const readableUrl = await getReadableAvatarUrl(path)
  return { publicUrl: readableUrl, path }
}

async function maybeUploadAvatar (ownerId, id) {
  if (!avatarFile.value) return null

  avatarUploading.value = true
  try {
    const { publicUrl } = await uploadAvatarToStorage({
      ownerId,
      patientId: id,
      file: avatarFile.value
    })

    // UI
    form.value.avatar_url = publicUrl
    avatarFile.value = null
    revokePreview()
    avatarPreviewUrl.value = publicUrl

    // DB
    await updatePatient(id, { avatar_url: publicUrl })

    return publicUrl
  } catch (e) {
    toast.add({
      severity: 'warn',
      summary: 'Avatar',
      detail: e?.message || 'Falha ao enviar avatar.',
      life: 4500
    })
    return null
  } finally {
    avatarUploading.value = false
  }
}

// ------------------------------------------------------
// Form state
// ------------------------------------------------------
function resetForm () {
  return {
    nome_completo: '',
    telefone: '',
    email_principal: '',
    email_alternativo: '',
    telefone_alternativo: '',
    data_nascimento: '',
    genero: '',
    estado_civil: '',
    cpf: '',
    rg: '',
    naturalidade: '',
    observacoes: '',
    onde_nos_conheceu: '',
    encaminhado_por: '',

    cep: '',
    pais: 'Brasil',
    cidade: '',
    estado: 'SP',
    endereco: '',
    numero: '',
    bairro: '',
    complemento: '',

    escolaridade: '',
    profissao: '',
    nome_parente: '',
    grau_parentesco: '',
    telefone_parente: '',

    nome_responsavel: '',
    cpf_responsavel: '',
    telefone_responsavel: '',
    observacao_responsavel: '',
    cobranca_no_responsavel: false,

    notas_internas: '',
    avatar_url: ''
  }
}

const form = ref(resetForm())

// ------------------------------------------------------
// Helpers: dígitos / formatação
// ------------------------------------------------------
function digitsOnly (v) {
  const s = String(v ?? '').replace(/\D/g, '')
  return s || ''
}

function fmtCPF (v) {
  const digits = digitsOnly(v).slice(0, 11)
  if (!digits) return ''
  return digits
    .replace(/^(\d{3})(\d)/, '$1.$2')
    .replace(/^(\d{3})\.(\d{3})(\d)/, '$1.$2.$3')
    .replace(/\.(\d{3})(\d)/, '.$1-$2')
}

function fmtRG (v) {
  if (!v) return ''
  const digits = digitsOnly(v).slice(0, 9)
  if (!digits) return ''
  return digits
    .replace(/^(\d{2})(\d)/, '$1.$2')
    .replace(/^(\d{2})\.(\d{3})(\d)/, '$1.$2.$3')
    .replace(/\.(\d{3})(\d)/, '.$1-$2')
}

function fmtPhone (digitsOrFormatted) {
  const digits = digitsOnly(digitsOrFormatted)
  if (!digits) return ''
  if (digits.length === 11) return digits.replace(/^(\d{2})(\d{5})(\d{4})$/, '($1) $2-$3')
  if (digits.length === 10) return digits.replace(/^(\d{2})(\d{4})(\d{4})$/, '($1) $2-$3')
  return digits
}

// ------------------------------------------------------
// Helpers: data DD-MM-AAAA <-> ISO
// ------------------------------------------------------
function parseDDMMYYYY (s) {
  const str = String(s || '').trim()
  const m = /^(\d{2})-(\d{2})-(\d{4})$/.exec(str)
  if (!m) return null
  const dd = Number(m[1])
  const mm = Number(m[2])
  const yyyy = Number(m[3])
  const dt = new Date(yyyy, mm - 1, dd)
  if (Number.isNaN(dt.getTime())) return null
  if (dt.getFullYear() !== yyyy || dt.getMonth() !== mm - 1 || dt.getDate() !== dd) return null
  return dt
}

function toISODateFromDDMMYYYY (s) {
  const dt = parseDDMMYYYY(s)
  if (!dt) return null
  const yyyy = String(dt.getFullYear()).padStart(4, '0')
  const mm = String(dt.getMonth() + 1).padStart(2, '0')
  const dd = String(dt.getDate()).padStart(2, '0')
  return `${yyyy}-${mm}-${dd}`
}

function isoToDDMMYYYY (value) {
  if (!value) return ''
  const s = String(value).trim()

  if (/^\d{2}-\d{2}-\d{4}$/.test(s)) return s

  const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(s)
  if (m) return `${m[3]}-${m[2]}-${m[1]}`

  const d = new Date(s)
  if (Number.isNaN(d.getTime())) return ''
  const dd = String(d.getDate()).padStart(2, '0')
  const mm = String(d.getMonth() + 1).padStart(2, '0')
  const yyyy = d.getFullYear()
  return `${dd}-${mm}-${yyyy}`
}

const ageLabel = computed(() => {
  const dt = parseDDMMYYYY(form.value?.data_nascimento)
  if (!dt) return '—'
  const now = new Date()
  let age = now.getFullYear() - dt.getFullYear()
  const mm = now.getMonth() - dt.getMonth()
  if (mm < 0 || (mm === 0 && now.getDate() < dt.getDate())) age--
  if (age < 0 || age > 130) return '—'
  return `${age} anos`
})

// ------------------------------------------------------
// map DB -> Form
// ------------------------------------------------------
function mapDbToForm (p) {
  return {
    ...resetForm(),

    nome_completo: p.nome_completo ?? '',
    telefone: fmtPhone(p.telefone ?? ''),
    email_principal: p.email_principal ?? '',
    email_alternativo: p.email_alternativo ?? '',
    telefone_alternativo: fmtPhone(p.telefone_alternativo ?? ''),

    data_nascimento: p.data_nascimento ? isoToDDMMYYYY(p.data_nascimento) : '',

    genero: p.genero ?? '',
    estado_civil: p.estado_civil ?? '',
    cpf: fmtCPF(p.cpf ?? ''),
    rg: fmtRG(p.rg ?? ''),
    naturalidade: p.naturalidade ?? '',

    observacoes: p.observacoes ?? '',
    onde_nos_conheceu: p.onde_nos_conheceu ?? '',
    encaminhado_por: p.encaminhado_por ?? '',

    cep: p.cep ?? '',
    pais: p.pais ?? 'Brasil',
    cidade: p.cidade ?? '',
    estado: p.estado ?? 'SP',
    endereco: p.endereco ?? '',
    numero: p.numero ?? '',
    bairro: p.bairro ?? '',
    complemento: p.complemento ?? '',

    escolaridade: p.escolaridade ?? '',
    profissao: p.profissao ?? '',
    nome_parente: p.nome_parente ?? '',
    grau_parentesco: p.grau_parentesco ?? '',
    telefone_parente: fmtPhone(p.telefone_parente ?? ''),

    nome_responsavel: p.nome_responsavel ?? '',
    cpf_responsavel: fmtCPF(p.cpf_responsavel ?? ''),
    telefone_responsavel: fmtPhone(p.telefone_responsavel ?? ''),
    observacao_responsavel: p.observacao_responsavel ?? '',
    cobranca_no_responsavel: !!p.cobranca_no_responsavel,

    notas_internas: p.notas_internas ?? '',
    avatar_url: p.avatar_url ?? ''
  }
}

// ------------------------------------------------------
// Owner (auth)
// ------------------------------------------------------
async function getOwnerId () {
  const { data, error } = await supabase.auth.getUser()
  if (error) throw error
  const uid = data?.user?.id
  if (!uid) throw new Error('Sessão inválida (auth.getUser).')
  return uid
}

// ------------------------------------------------------
// Sanitização
// ------------------------------------------------------
const PACIENTES_COLUNAS_PERMITIDAS = new Set([
  'owner_id',
  'tenant_id',
  'responsible_member_id',
  'nome_completo',
  'telefone',
  'email_principal',
  'email_alternativo',
  'telefone_alternativo',
  'data_nascimento',
  'genero',
  'estado_civil',
  'cpf',
  'rg',
  'naturalidade',
  'observacoes',
  'onde_nos_conheceu',
  'encaminhado_por',
  'pais',
  'cep',
  'cidade',
  'estado',
  'endereco',
  'numero',
  'bairro',
  'complemento',
  'escolaridade',
  'profissao',
  'nome_parente',
  'grau_parentesco',
  'telefone_parente',
  'nome_responsavel',
  'cpf_responsavel',
  'telefone_responsavel',
  'observacao_responsavel',
  'cobranca_no_responsavel',
  'notas_internas',
  'avatar_url'
])

function sanitizePayload (raw, ownerId) {
  const payload = {
    owner_id: ownerId,

    nome_completo: raw.nome_completo,
    telefone: raw.telefone,
    email_principal: raw.email_principal,

    email_alternativo: raw.email_alternativo || null,
    telefone_alternativo: raw.telefone_alternativo || null,

    data_nascimento: raw.data_nascimento || null,
    genero: raw.genero || null,
    estado_civil: raw.estado_civil || null,

    cpf: raw.cpf || null,
    rg: raw.rg || null,
    naturalidade: raw.naturalidade || null,

    observacoes: raw.observacoes || null,
    onde_nos_conheceu: raw.onde_nos_conheceu || null,
    encaminhado_por: raw.encaminhado_por || null,

    cep: raw.cep || null,
    pais: raw.pais || null,
    cidade: raw.cidade || null,
    estado: raw.estado || null,
    endereco: raw.endereco || null,
    numero: raw.numero || null,
    bairro: raw.bairro || null,
    complemento: raw.complemento || null,

    escolaridade: raw.escolaridade || null,
    profissao: raw.profissao || null,
    nome_parente: raw.nome_parente || null,
    grau_parentesco: raw.grau_parentesco || null,
    telefone_parente: raw.telefone_parente || null,

    nome_responsavel: raw.nome_responsavel || null,
    cpf_responsavel: raw.cpf_responsavel || null,
    telefone_responsavel: raw.telefone_responsavel || null,
    observacao_responsavel: raw.observacao_responsavel || null,
    cobranca_no_responsavel: !!raw.cobranca_no_responsavel,

    notas_internas: raw.notas_internas || null,
    avatar_url: raw.avatar_url || null
  }

  // strings vazias -> null e trim
  Object.keys(payload).forEach(k => {
    if (payload[k] === '') payload[k] = null
    if (typeof payload[k] === 'string') {
      const t = payload[k].trim()
      payload[k] = t === '' ? null : t
    }
  })

  payload.cpf = payload.cpf ? digitsOnly(payload.cpf) : null
  payload.rg = payload.rg ? digitsOnly(payload.rg) : null
  payload.cpf_responsavel = payload.cpf_responsavel ? digitsOnly(payload.cpf_responsavel) : null

  payload.telefone = payload.telefone ? digitsOnly(payload.telefone) : null
  payload.telefone_alternativo = payload.telefone_alternativo ? digitsOnly(payload.telefone_alternativo) : null
  payload.telefone_parente = payload.telefone_parente ? digitsOnly(payload.telefone_parente) : null
  payload.telefone_responsavel = payload.telefone_responsavel ? digitsOnly(payload.telefone_responsavel) : null

  payload.data_nascimento = payload.data_nascimento
    ? (toISODateFromDDMMYYYY(payload.data_nascimento) || null)
    : null

  const filtrado = {}
  Object.keys(payload).forEach(k => {
    if (PACIENTES_COLUNAS_PERMITIDAS.has(k)) filtrado[k] = payload[k]
  })

  return filtrado
}

// ------------------------------------------------------
// Supabase: lists / get / relations
// ------------------------------------------------------
async function listGroups () {
  const probe = await supabase.from('patient_groups').select('*').limit(1)
  if (probe.error) throw probe.error

  const row = probe.data?.[0] || {}
  const hasPT = ('nome' in row) || ('cor' in row)
  const hasEN = ('name' in row) || ('color' in row)

  if (hasPT) {
    const { data, error } = await supabase
      .from('patient_groups')
      .select('id,nome,descricao,cor,is_system,is_active')
      .eq('is_active', true)
      .order('nome', { ascending: true })
    if (error) throw error
    return (data || []).map(g => ({ ...g, name: g.nome, color: g.cor }))
  }

  if (hasEN) {
    const { data, error } = await supabase
      .from('patient_groups')
      .select('id,name,description,color,is_system,is_active')
      .eq('is_active', true)
      .order('name', { ascending: true })
    if (error) throw error
    return (data || []).map(g => ({ ...g, nome: g.name, cor: g.color }))
  }

  const { data, error } = await supabase.from('patient_groups').select('*').order('id', { ascending: true })
  if (error) throw error
  return data || []
}

async function listTags () {
  const probe = await supabase.from('patient_tags').select('*').limit(1)
  if (probe.error) throw probe.error

  const row = probe.data?.[0] || {}
  const hasEN = ('name' in row) || ('color' in row)
  const hasPT = ('nome' in row) || ('cor' in row)

  if (hasEN) {
    const { data, error } = await supabase.from('patient_tags').select('id,name,color').order('name', { ascending: true })
    if (error) throw error
    return data || []
  }

  if (hasPT) {
    const { data, error } = await supabase.from('patient_tags').select('id,nome,cor').order('nome', { ascending: true })
    if (error) throw error
    return (data || []).map(t => ({ ...t, name: t.nome, color: t.cor }))
  }

  const { data, error } = await supabase.from('patient_tags').select('*').order('id', { ascending: true })
  if (error) throw error
  return (data || []).map(t => ({ ...t, name: t.name ?? t.nome ?? '', color: t.color ?? t.cor ?? null }))
}

async function getPatientById (id) {
  const { data, error } = await supabase.from('patients').select('*').eq('id', id).single()
  if (error) throw error
  return data
}

async function getPatientRelations (id) {
  const { data: g, error: ge } = await supabase
    .from('patient_group_patient')
    .select('patient_group_id')
    .eq('patient_id', id)
  if (ge) throw ge

  const { data: t, error: te } = await supabase
    .from('patient_patient_tag')
    .select('tag_id')
    .eq('patient_id', id)
  if (te) throw te

  return {
    groupIds: (g || []).map(x => x.patient_group_id).filter(Boolean),
    tagIds: (t || []).map(x => x.tag_id).filter(Boolean)
  }
}

async function createPatient (payload) {
  const { data, error } = await supabase.from('patients').insert(payload).select('id').single()
  if (error) throw error
  return data
}

async function updatePatient (id, payload) {
  const { error } = await supabase
    .from('patients')
    .update({ ...payload, updated_at: new Date().toISOString() })
    .eq('id', id)

  if (error) throw error
}

// ------------------------------------------------------
// Relations state
// ------------------------------------------------------
const groups = ref([])
const tags = ref([])
const grupoIdSelecionado = ref(null)
const tagIdsSelecionadas = ref([])

async function replacePatientGroups (patient_id, groupId) {
  const { error: delErr } = await supabase.from('patient_group_patient').delete().eq('patient_id', patient_id)
  if (delErr) throw delErr
  if (!groupId) return
  const { tenantId } = await resolveTenantContextOrFail()
  const { error: insErr } = await supabase.from('patient_group_patient').insert({ patient_id, patient_group_id: groupId, tenant_id: tenantId })
  if (insErr) throw insErr
}

async function replacePatientTags (patient_id, tagIds) {
  const ownerId = await getOwnerId()

  const { error: delErr } = await supabase
    .from('patient_patient_tag')
    .delete()
    .eq('patient_id', patient_id)
    .eq('owner_id', ownerId)
  if (delErr) throw delErr

  const clean = Array.from(new Set([...(tagIds || [])].filter(Boolean)))
  if (!clean.length) return

  const { tenantId } = await resolveTenantContextOrFail()
  const rows = clean.map(tag_id => ({ owner_id: ownerId, patient_id, tag_id, tenant_id: tenantId }))
  const { error: insErr } = await supabase.from('patient_patient_tag').insert(rows)
  if (insErr) throw insErr
}

// ------------------------------------------------------
// CEP (ViaCEP)
// ------------------------------------------------------
async function fetchCep (cepRaw) {
  const cep = digitsOnly(cepRaw)
  if (cep.length !== 8) return null
  const res = await fetch(`https://viacep.com.br/ws/${cep}/json/`)
  const data = await res.json()
  if (!data || data.erro) return null
  return data
}

async function onCepBlur () {
  try {
    const d = await fetchCep(form.value.cep)
    if (!d) return
    form.value.cidade = d.localidade || form.value.cidade
    form.value.estado = d.uf || form.value.estado
    form.value.bairro = d.bairro || form.value.bairro
    form.value.endereco = d.logradouro || form.value.endereco
    if (!form.value.complemento) form.value.complemento = d.complemento || ''
  } catch (_) {}
}

// ------------------------------------------------------
// UI state
// ------------------------------------------------------
const loading = ref(false)
const saving = ref(false)
const deleting = ref(false)

// ------------------------------------------------------
// Fetch (load everything)
// ------------------------------------------------------
async function fetchAll () {
  loading.value = true
  try {
    const [gRes, tRes] = await Promise.allSettled([listGroups(), listTags()])

    if (gRes.status === 'fulfilled') groups.value = gRes.value || []
    else {
      groups.value = []
      console.warn('[listGroups error]', gRes.reason)
      toast.add({ severity: 'warn', summary: 'Grupos', detail: gRes.reason?.message || 'Falha ao carregar grupos', life: 3500 })
    }

    if (tRes.status === 'fulfilled') tags.value = tRes.value || []
    else {
      tags.value = []
      console.warn('[listTags error]', tRes.reason)
      toast.add({ severity: 'warn', summary: 'Tags', detail: tRes.reason?.message || 'Falha ao carregar tags', life: 3500 })
    }

    if (isEdit.value) {
      const p = await getPatientById(patientId.value)
      form.value = mapDbToForm(p)

      // se já tinha avatar no banco, garante preview
      avatarPreviewUrl.value = form.value.avatar_url || ''

      const rel = await getPatientRelations(patientId.value)
      grupoIdSelecionado.value = rel.groupIds?.[0] || null
      tagIdsSelecionadas.value = rel.tagIds || []
    } else {
      //form.value = resetForm()
      grupoIdSelecionado.value = null
      tagIdsSelecionadas.value = []
      avatarFile.value = null
      revokePreview()
    }
  } catch (err) {
    toast.add({ severity: 'error', summary: 'Erro', detail: err?.message || 'Falha ao carregar cadastro', life: 3500 })
  } finally {
    loading.value = false
  }
}

watch(() => route.params?.id, fetchAll, { immediate: true })
onMounted(fetchAll)

// ------------------------------------------------------
// Tenant resolve (robusto)
// ------------------------------------------------------
async function resolveTenantContextOrFail () {
  const { data: authData, error: authError } = await supabase.auth.getUser()
  if (authError) throw authError
  const uid = authData?.user?.id
  if (!uid) throw new Error('Sessão inválida.')

  // 1) tenta pelo store
  const storeTid = await getCurrentTenantId()
  if (storeTid) {
    try {
      const mid = await getCurrentMemberId(storeTid)
      return { tenantId: storeTid, memberId: mid }
    } catch (_) {
      // cai pro fallback (último membership active)
    }
  }

  // 2) fallback
  const { data, error } = await supabase
    .from('tenant_members')
    .select('id, tenant_id')
    .eq('user_id', uid)
    .eq('status', 'active')
    .order('created_at', { ascending: false })
    .limit(1)
    .single()

  if (error) throw error
  if (!data?.tenant_id || !data?.id) throw new Error('Responsible member not found')

  return { tenantId: data.tenant_id, memberId: data.id }
}

// ------------------------------------------------------
// Submit
// ------------------------------------------------------
async function onSubmit () {
  try {
    saving.value = true

    const ownerId = await getOwnerId()
    const { tenantId, memberId } = await resolveTenantContextOrFail()

    // depois do sanitize
    const payload = sanitizePayload(form.value, ownerId)
    payload.tenant_id = tenantId
    payload.responsible_member_id = memberId

    // ✅ validações mínimas (NÃO DEIXA CHEGAR NO BANCO)
    const nome = String(form.value?.nome_completo || '').trim()
    if (!nome) {
      toast.add({
        severity: 'warn',
        summary: 'Nome obrigatório',
        detail: 'Preencha “Nome completo” para salvar o paciente.',
        life: 3500
      })

      // abre o painel certo (você já tem navItems: "Informações pessoais" é o 0)
      await openPanel(0)
      return
    }

    // ---------------------------
    // EDIT
    // ---------------------------
    if (isEdit.value) {
      await updatePatient(patientId.value, payload)

      // ✅ Se houver avatar selecionado, sobe e grava avatar_url
      await maybeUploadAvatar(ownerId, patientId.value)

      await replacePatientGroups(patientId.value, grupoIdSelecionado.value)
      await replacePatientTags(patientId.value, tagIdsSelecionadas.value)

      toast.add({ severity: 'success', summary: 'Salvo', detail: 'Paciente atualizado.', life: 2500 })
      return
    }

    // ---------------------------
    // CREATE
    // ---------------------------
    const created = await createPatient(payload)

    // ✅ upload do avatar usando ID recém-criado
    await maybeUploadAvatar(ownerId, created.id)

    await replacePatientGroups(created.id, grupoIdSelecionado.value)
    await replacePatientTags(created.id, tagIdsSelecionadas.value)

    toast.add({ severity: 'success', summary: 'Salvo', detail: 'Paciente cadastrado.', life: 2500 })

    // ✅ NÃO navega para /cadastro/:id (fica em /admin/pacientes/cadastro)
    // Em vez disso, reseta o formulário para novo cadastro:
    form.value = resetForm()
    grupoIdSelecionado.value = null
    tagIdsSelecionadas.value = []

    avatarFile.value = null
    revokePreview()
    avatarPreviewUrl.value = ''

    // volta pro primeiro painel (UX boa)
    await openPanel(0)

    return
  } catch (e) {
    console.error(e)
    toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao salvar paciente.', life: 4000 })
  } finally {
    saving.value = false
  }
}
// ------------------------------------------------------
// Delete
// ------------------------------------------------------
function confirmDelete () {
  if (!isEdit.value) return
  confirm.require({
    header: 'Excluir paciente',
    message: 'Tem certeza que deseja excluir este paciente? Essa ação não pode ser desfeita.',
    icon: 'pi pi-exclamation-triangle',
    acceptLabel: 'Excluir',
    rejectLabel: 'Cancelar',
    acceptClass: 'p-button-danger',
    accept: async () => doDelete()
  })
}

async function doDelete () {
  if (!isEdit.value) return
  deleting.value = true
  try {
    const pid = patientId.value

    const { error: e1 } = await supabase.from('patient_group_patient').delete().eq('patient_id', pid)
    if (e1) throw e1

    const { error: e2 } = await supabase.from('patient_patient_tag').delete().eq('patient_id', pid)
    if (e2) throw e2

    const { error: e3 } = await supabase.from('patients').delete().eq('id', pid)
    if (e3) throw e3

    toast.add({ severity: 'success', summary: 'Excluído', detail: 'Paciente excluído.', life: 2500 })
    goBack()
  } catch (err) {
    toast.add({ severity: 'error', summary: 'Erro', detail: err?.message || 'Falha ao excluir paciente', life: 4000 })
  } finally {
    deleting.value = false
  }
}

// ------------------------------------------------------
// Fake fill (opcional) — mantive como você tinha
// ------------------------------------------------------
function randInt (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min }
function pick (arr) { return arr[randInt(0, arr.length - 1)] }
function maybe (p = 0.5) { return Math.random() < p }
function pad2 (n) { return String(n).padStart(2, '0') }

function randomDateDDMMYYYY (minAge = 6, maxAge = 75) {
  const now = new Date()
  const age = randInt(minAge, maxAge)
  const year = now.getFullYear() - age
  const month = randInt(1, 12)
  const day = randInt(1, 28)
  return `${pad2(day)}-${pad2(month)}-${year}`
}

function randomPhoneBR () {
  const ddd = randInt(11, 99)
  const nine = maybe(0.8) ? '9' : ''
  const p1 = randInt(1000, 9999)
  const p2 = randInt(1000, 9999)
  return `+55 (${ddd}) ${nine}${p1}-${p2}`
}

function randomCEP () { return `${randInt(10000, 99999)}-${randInt(100, 999)}` }

function generateCPF () {
  const n = Array.from({ length: 9 }, () => randInt(0, 9))
  const calcDV = (base) => {
    let sum = 0
    for (let i = 0; i < base.length; i++) sum += base[i] * (base.length + 1 - i)
    const mod = sum % 11
    return mod < 2 ? 0 : 11 - mod
  }
  const d1 = calcDV(n)
  const d2 = calcDV([...n, d1])
  const cpf = [...n, d1, d2].join('')
  if (/^(\d)\1+$/.test(cpf)) return generateCPF()
  return cpf.replace(/^(\d{3})(\d{3})(\d{3})(\d{2})$/, '$1.$2.$3-$4')
}

function randomEmailFromName (name) {
  const slug = String(name || 'paciente')
    .normalize('NFD').replace(/[\u0300-\u036f]/g, '')
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '.')
    .replace(/(^\.)|(\.$)/g, '')
  return `${slug}.${randInt(10, 999)}@email.com`
}

function fillRandomPatient () {
  const first = ['Ana','Bruno','Carla','Daniel','Eduarda','Felipe','Giovana','Henrique','Isabela','João','Larissa','Marcos','Nathalia','Otávio','Paula','Rafael','Sabrina','Thiago','Vanessa','Yasmin']
  const last = ['Silva','Santos','Oliveira','Souza','Pereira','Lima','Ferreira','Almeida','Costa','Gomes','Ribeiro','Carvalho','Martins','Araújo','Barbosa']
  const cities = ['São Carlos','Ribeirão Preto','Campinas','São Paulo','Araraquara','Bauru','Sorocaba','Santos']
  const states = ['SP','RJ','MG','PR','SC','RS','BA','PE']
  const streets = ['Rua das Flores','Av. Brasil','Rua XV de Novembro','Av. São Carlos','Rua das Acácias']
  const bairros = ['Centro','Jardim Paulista','Vila Prado','Santa Felícia','Cidade Jardim']
  const escolaridades = ['Ensino Fundamental','Ensino Médio','Superior incompleto','Superior completo','Pós-graduação']
  const profissoes = ['Estudante','Professora','Desenvolvedor','Vendedor','Enfermeira','Autônomo','Servidor público']
  const fontes = ['Instagram','Google','Indicação','Site','Threads','Outro']
  const parentescos = ['Mãe','Pai','Irmã','Irmão','Cônjuge','Tia','Avó','Avô']

  const nomeCompleto = `${pick(first)} ${pick(last)} ${pick(last)}`
  const cidade = pick(cities)
  const estado = pick(states)

  form.value = {
    ...resetForm(),
    nome_completo: nomeCompleto,
    telefone: randomPhoneBR(),
    email_principal: randomEmailFromName(nomeCompleto),
    email_alternativo: `alt.${randInt(10,999)}@email.com`,
    telefone_alternativo: randomPhoneBR(),
    data_nascimento: randomDateDDMMYYYY(6, 78),

    genero: pick(['Feminino','Masculino','Não-binário','Prefere não informar','Outro']),
    estado_civil: pick(['Solteiro(a)','Casado(a)','União estável','Divorciado(a)','Separado(a)','Viúvo(a)']),
    cpf: fmtCPF(generateCPF()),
    rg: fmtRG(String(randInt(10000000, 999999999))),
    naturalidade: cidade,

    observacoes: 'Paciente relata ansiedade e sobrecarga emocional.',
    onde_nos_conheceu: pick(fontes),
    encaminhado_por: `${pick(first)} ${pick(last)}`,

    cep: randomCEP(),
    pais: 'Brasil',
    cidade: cidade,
    estado: estado,
    endereco: pick(streets),
    numero: String(randInt(10, 9999)),
    bairro: pick(bairros),
    complemento: `Apto ${randInt(10, 999)}`,

    escolaridade: pick(escolaridades),
    profissao: pick(profissoes),
    nome_parente: `${pick(first)} ${pick(last)}`,
    grau_parentesco: pick(parentescos),
    telefone_parente: randomPhoneBR(),

    nome_responsavel: `${pick(first)} ${pick(last)} ${pick(last)}`,
    cpf_responsavel: fmtCPF(generateCPF()),
    telefone_responsavel: randomPhoneBR(),
    observacao_responsavel: 'Responsável ciente do contrato.',
    cobranca_no_responsavel: true,

    notas_internas: 'Paciente apresenta discurso organizado. Acompanhar evolução clínica.',
    avatar_url: ''
  }

  if (Array.isArray(groups.value) && groups.value.length) grupoIdSelecionado.value = pick(groups.value).id
  if (Array.isArray(tags.value) && tags.value.length) {
    const shuffled = [...tags.value].sort(() => Math.random() - 0.5)
    tagIdsSelecionadas.value = shuffled.slice(0, randInt(1, Math.min(3, tags.value.length))).map(t => t.id)
  }

  toast.add({ severity: 'info', summary: 'Preenchido', detail: 'Paciente preenchido com dados fictícios.', life: 2500 })
}

const genderOptions = [
  { label: 'Feminino', value: 'Feminino' },
  { label: 'Masculino', value: 'Masculino' },
  { label: 'Não-binário', value: 'Não-binário' },
  { label: 'Prefere não informar', value: 'Prefere não informar' },
  { label: 'Outro', value: 'Outro' }
]

const maritalStatusOptions = [
  { label: 'Solteiro(a)', value: 'Solteiro(a)' },
  { label: 'Casado(a)', value: 'Casado(a)' },
  { label: 'União estável', value: 'União estável' },
  { label: 'Divorciado(a)', value: 'Divorciado(a)' },
  { label: 'Separado(a)', value: 'Separado(a)' },
  { label: 'Viúvo(a)', value: 'Viúvo(a)' },
  { label: 'Prefere não informar', value: 'Prefere não informar' }
]

// ------------------------------------------------------
// Dialogs: criar Grupo / Tag
// ------------------------------------------------------
const createGroupDialog = ref(false)
const createGroupSaving = ref(false)
const createGroupError = ref('')
const newGroup = ref({ name: '', color: '#6366F1' })

const createTagDialog = ref(false)
const createTagSaving = ref(false)
const createTagError = ref('')
const newTag = ref({ name: '', color: '#22C55E' })

function openGroupDlg () {
  createGroupError.value = ''
  newGroup.value = { name: '', color: '#6366F1' }
  createGroupDialog.value = true
}

function openTagDlg () {
  createTagError.value = ''
  newTag.value = { name: '', color: '#22C55E' }
  createTagDialog.value = true
}

async function createGroupPersist () {
  if (createGroupSaving.value) return
  createGroupError.value = ''

  const name = String(newGroup.value?.name || '').trim()
  const color = String(newGroup.value?.color || '').trim() || '#6366F1'
  if (!name) { createGroupError.value = 'Informe um nome para o grupo.'; return }

  createGroupSaving.value = true
  try {
    const ownerId = await getOwnerId()
    const { tenantId } = await resolveTenantContextOrFail()
    let createdId = null

    const { data, error } = await supabase
      .from('patient_groups')
      .insert({ owner_id: ownerId, tenant_id: tenantId, nome: name, descricao: null, cor: color, is_system: false, is_active: true })
      .select('id')
      .single()

    if (error) throw error
    createdId = data?.id || null

    groups.value = await listGroups()
    if (createdId) grupoIdSelecionado.value = createdId

    toast.add({ severity: 'success', summary: 'Grupo', detail: 'Grupo criado.', life: 2500 })
    createGroupDialog.value = false
  } catch (e) {
    const msg = e?.message || ''
    if (e?.code === '23505' || /duplicate key value/i.test(msg)) {
      createGroupError.value = 'Já existe um grupo com esse nome.'
    } else {
      createGroupError.value = msg || 'Falha ao criar grupo.'
    }
  } finally {
    createGroupSaving.value = false
  }
}

async function createTagPersist () {
  if (createTagSaving.value) return
  createTagError.value = ''

  const name = String(newTag.value?.name || '').trim()
  const color = String(newTag.value?.color || '').trim() || '#22C55E'
  if (!name) { createTagError.value = 'Informe um nome para a tag.'; return }

  createTagSaving.value = true
  try {
    const ownerId = await getOwnerId()
    const { tenantId } = await resolveTenantContextOrFail()
    let createdId = null

    const { data, error } = await supabase
      .from('patient_tags')
      .insert({ owner_id: ownerId, tenant_id: tenantId, nome: name, cor: color })
      .select('id')
      .single()

    if (error) throw error
    createdId = data?.id || null

    tags.value = await listTags()
    if (createdId) {
      const set = new Set([...(tagIdsSelecionadas.value || []), createdId])
      tagIdsSelecionadas.value = Array.from(set)
    }

    toast.add({ severity: 'success', summary: 'Tag', detail: 'Tag criada.', life: 2500 })
    createTagDialog.value = false
  } catch (e) {
    const msg = e?.message || ''
    if (e?.code === '23505' || /duplicate key value/i.test(msg)) {
      createTagError.value = 'Já existe uma tag com esse nome.'
    } else {
      createTagError.value = msg || 'Falha ao criar tag.'
    }
  } finally {
    createTagSaving.value = false
  }
}
</script>

<template>
  <div class="min-h-screen bg-surface-50 dark:bg-surface-950">
    <Toast />
    <ConfirmDialog />

    <div class="px-3 py-3 md:px-4">
      <Card class="w-full max-w-[1100px] mx-auto">
        <template #title>
          <div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
            <div class="min-w-0">
              <div class="text-xl font-semibold text-surface-900 dark:text-surface-0">
                {{ isEdit ? 'Editar paciente' : 'Cadastrar paciente' }}
              </div>
              <div class="mt-1 text-sm text-surface-600 dark:text-surface-300">
                Idade: <b class="text-surface-900 dark:text-surface-0">{{ ageLabel }}</b>
              </div>
            </div>

            <div class="flex flex-wrap gap-2">
              <Button
				v-if="canSee('testMODE')"
                label="Preencher tudo"
                icon="pi pi-bolt"
                severity="secondary"
                outlined
                @click="fillRandomPatient"				
              />
              <Button
                label="Voltar"
                icon="pi pi-arrow-left"
                severity="secondary"
                outlined
                @click="goBack"
              />
              <Button
                v-if="isEdit"
                label="Excluir"
                icon="pi pi-trash"
                severity="danger"
                outlined
                :loading="deleting"
                @click="confirmDelete"
              />
              <Button
                label="Salvar"
                icon="pi pi-check"
                :loading="saving"
                @click="onSubmit"
              />
            </div>
          </div>
        </template>

        <template #content>
          <div v-if="loading" class="p-4 text-sm text-surface-600 dark:text-surface-300">
            Carregando…
          </div>

          <div v-else class="grid grid-cols-1 gap-4 xl:grid-cols-[260px_1fr]">
            <!-- SIDEBAR -->
            <aside
              class="rounded-2xl border border-surface-200 bg-white p-3 shadow-sm
                     dark:border-surface-800 dark:bg-surface-900
                     xl:sticky xl:top-3"
            >
              <!-- Avatar -->
              <div class="flex items-center justify-between gap-3 border-b border-surface-200 pb-3 dark:border-surface-800 xl:flex-col xl:items-center xl:justify-start">
                <div class="h-16 w-16 overflow-hidden rounded-full border border-surface-200 bg-surface-100 dark:border-surface-800 dark:bg-surface-800 xl:h-20 xl:w-20">
                  <img
                    v-if="avatarPreviewUrl || form.avatar_url"
                    :src="avatarPreviewUrl || form.avatar_url"
                    alt="Avatar do paciente"
                    class="h-full w-full object-cover"
                  />
                  <div v-else class="grid h-full w-full place-items-center">
                    <i class="pi pi-user text-2xl opacity-60"></i>
                  </div>
                </div>

                <div class="flex-1 xl:w-full">
                  <input
                    type="file"
                    accept="image/*"
                    class="block w-full text-sm file:mr-3 file:rounded-xl file:border-0 file:bg-surface-100 file:px-3 file:py-2 file:text-surface-900
                           hover:file:bg-surface-200
                           dark:file:bg-surface-800 dark:file:text-surface-0 dark:hover:file:bg-surface-700"
                    @change="onAvatarPicked"
                  />
                  <div class="mt-1 text-xs text-surface-600 dark:text-surface-300">
                    Avatar (opcional)
                    <span v-if="avatarUploading" class="ml-2">(enviando…)</span>
                  </div>
                </div>
              </div>

              <!-- NAV (>=1200px) -->
              <div v-if="!isCompact" class="mt-3 flex flex-col gap-2">
                <button
                  v-for="item in navItems"
                  :key="item.value"
                  type="button"
                  class="flex items-center gap-3 rounded-xl border px-3 py-2 text-left text-sm
                         border-transparent hover:bg-surface-100
                         dark:hover:bg-surface-800"
                  :class="activeValue === item.value
                    ? 'bg-primary-50 border-primary-200 text-primary-800 dark:bg-primary-900/20 dark:border-primary-700/40 dark:text-primary-200'
                    : 'text-surface-800 dark:text-surface-0'"
                  @click="openPanel(Number(item.value))"
                >
                  <i :class="item.icon" class="opacity-80"></i>
                  <span class="font-medium">{{ item.label }}</span>
                </button>
              </div>
            </aside>

            <!-- MAIN -->
            <main class="rounded-2xl border border-surface-200 bg-white p-3 shadow-sm dark:border-surface-800 dark:bg-surface-900">
              <!-- NAV COMPACT (<1200px): sticky + popover -->
              <div v-if="isCompact" class="sticky top-14 z-50 mb-3 border-b border-surface-200 bg-white py-2 dark:border-surface-800 dark:bg-surface-900">
                <Button
                  type="button"
                  class="w-full"
                  icon="pi pi-chevron-down"
                  iconPos="right"
                  :label="selectedNav ? selectedNav.label : 'Selecionar seção'"
                  @click="toggleNav($event)"
                />

                <Popover
                  ref="navPopover"
                  :pt="{
                    root: { class: 'z-[9999999]' }
                  }"
                >
                  <div class="flex min-w-[260px] flex-col gap-3">
                    <span class="block text-sm font-semibold text-surface-900 dark:text-surface-0">Seções</span>

                    <ul class="m-0 flex list-none flex-col gap-1 p-0">
                      <li
                        v-for="item in navItems"
                        :key="item.value"
                        class="flex cursor-pointer items-center gap-2 rounded-xl px-3 py-2 text-sm hover:bg-surface-100 dark:hover:bg-surface-800"
                        :class="activeValue === item.value ? 'bg-surface-100 dark:bg-surface-800' : ''"
                        @click="selectNav(item)"
                      >
                        <i :class="item.icon" class="opacity-80"></i>
                        <span class="font-medium">{{ item.label }}</span>
                      </li>
                    </ul>
                  </div>
                </Popover>
              </div>

              <Accordion :multiple="false" v-model:value="activeValue">
                <!-- 0 -->
                <AccordionPanel value="0">
                  <AccordionHeader :ref="el => setPanelHeaderRef(el, 0)">
                    1. Informações pessoais
                  </AccordionHeader>

                  <AccordionContent>
                    <div class="grid grid-cols-1 gap-4 xl:grid-cols-2">
                      <div class="xl:col-span-2">
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-user" />
                            <InputText id="f_nome" v-model="form.nome_completo" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_nome">Nome completo *</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-phone" />
                            <InputMask
                              id="f_telefone"
                              v-model="form.telefone"
                              mask="(99) 99999-9999"
                              :unmask="false"
                              class="w-full"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_telefone">Telefone / celular *</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-envelope" />
                            <InputText id="f_email" v-model="form.email_principal" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_email">E-mail principal *</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-envelope" />
                            <InputText id="f_email_alt" v-model="form.email_alternativo" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_email_alt">E-mail alternativo</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-phone" />
                            <InputMask
                              id="f_tel_alt"
                              v-model="form.telefone_alternativo"
                              mask="(99) 99999-9999"
                              :unmask="false"
                              class="w-full"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_tel_alt">Telefone alternativo</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-calendar" />
                            <InputMask
                              id="f_nasc"
                              v-model="form.data_nascimento"
                              mask="99-99-9999"
                              :unmask="false"
                              class="w-full"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_nasc">Data de nascimento</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-user" />
                            <Select
                              id="f_genero"
                              v-model="form.genero"
                              :options="genderOptions"
                              optionLabel="label"
                              optionValue="value"
                              class="w-full pl-[25px]"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_genero">Gênero</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-heart" />
                            <Select
                              id="f_estado_civil"
                              v-model="form.estado_civil"
                              :options="maritalStatusOptions"
                              optionLabel="label"
                              optionValue="value"
                              class="w-full pl-[25px]"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_estado_civil">Estado civil</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-id-card" />
                            <InputMask
                              id="f_cpf"
                              v-model="form.cpf"
                              mask="999.999.999-99"
                              :unmask="false"
                              class="w-full"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_cpf">CPF</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-id-card" />
                            <InputText id="f_rg" v-model="form.rg" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_rg">RG</label>
                        </FloatLabel>
                      </div>

                      <div class="xl:col-span-2">
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-map" />
                            <InputText id="f_nat" v-model="form.naturalidade" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_nat">Naturalidade</label>
                        </FloatLabel>
                      </div>

                      <div class="xl:col-span-2">
                        <FloatLabel variant="on">
                          <Textarea id="f_obs" v-model="form.observacoes" rows="3" class="w-full" variant="filled" />
                          <label for="f_obs">Observações</label>
                        </FloatLabel>
                      </div>

                      <!-- Grupos -->
                      <div>
                        <div class="flex gap-2">
                          <div class="w-full">
                            <FloatLabel variant="on">
                              <IconField>
                                <InputIcon class="pi pi-folder-open" />
                                <Select
                                  id="f_group"
                                  v-model="grupoIdSelecionado"
                                  :options="groups"
                                  optionLabel="nome"
                                  optionValue="id"
                                  class="w-full pl-[25px]"
                                  showClear
                                  filter
                                  variant="filled"
                                />
                              </IconField>
                              <label for="f_group">Grupo</label>
                            </FloatLabel>
                            <small class="mt-1 block text-xs text-surface-600 dark:text-surface-300">
                              Usado para puxar um modelo de anamnese.
                            </small>
                          </div>

                          <Button icon="pi pi-plus" severity="secondary" outlined @click="openGroupDlg('create')" />
                        </div>
                      </div>

                      <!-- Tags -->
                      <div>
                        <div class="flex gap-2">
                          <div class="w-full">
                            <FloatLabel variant="on">
                              <IconField>
                                <InputIcon class="pi pi-tag" />
                                <MultiSelect
                                  id="f_tags"
                                  v-model="tagIdsSelecionadas"
                                  :options="tags"
                                  optionLabel="name"
                                  optionValue="id"
                                  class="w-full pl-[25px]"
                                  display="chip"
                                  filter
                                  variant="filled"
                                />
                              </IconField>
                              <label for="f_tags">Tags</label>
                            </FloatLabel>
                          </div>

                          <Button icon="pi pi-plus" severity="secondary" outlined @click="openTagDlg('create')" />
                        </div>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-megaphone" />
                            <InputText id="f_lead" v-model="form.onde_nos_conheceu" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_lead">Como chegou até mim?</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-share-alt" />
                            <InputText id="f_ref" v-model="form.encaminhado_por" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_ref">Encaminhado por</label>
                        </FloatLabel>
                      </div>
                    </div>
                  </AccordionContent>
                </AccordionPanel>

                <!-- 1 -->
                <AccordionPanel value="1">
                  <AccordionHeader :ref="el => setPanelHeaderRef(el, 1)">2. Endereço</AccordionHeader>
                  <AccordionContent>
                    <div class="grid grid-cols-1 gap-4 xl:grid-cols-2">
                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-map-marker" />
                            <InputText id="f_cep" v-model="form.cep" class="w-full" @blur="onCepBlur" variant="filled" />
                          </IconField>
                          <label for="f_cep">CEP</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-globe" />
                            <InputText id="f_country" v-model="form.pais" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_country">País</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-building" />
                            <InputText id="f_city" v-model="form.cidade" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_city">Cidade</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-compass" />
                            <InputText id="f_state" v-model="form.estado" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_state">Estado</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-map" />
                            <InputText id="f_address" v-model="form.endereco" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_address">Endereço</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-hashtag" />
                            <InputText id="f_number" v-model="form.numero" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_number">Número</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-map-marker" />
                            <InputText id="f_neighborhood" v-model="form.bairro" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_neighborhood">Bairro</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-align-left" />
                            <InputText id="f_complement" v-model="form.complemento" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_complement">Complemento</label>
                        </FloatLabel>
                      </div>
                    </div>
                  </AccordionContent>
                </AccordionPanel>

                <!-- 2 -->
                <AccordionPanel value="2">
                  <AccordionHeader :ref="el => setPanelHeaderRef(el, 2)">3. Dados adicionais</AccordionHeader>
                  <AccordionContent>
                    <div class="grid grid-cols-1 gap-4 xl:grid-cols-2">
                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-book" />
                            <InputText id="f_escolaridade" v-model="form.escolaridade" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_escolaridade">Escolaridade</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-briefcase" />
                            <InputText id="f_profissao" v-model="form.profissao" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_profissao">Profissão</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-user" />
                            <InputText id="f_parente_nome" v-model="form.nome_parente" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_parente_nome">Nome de um parente</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-users" />
                            <InputText id="f_parentesco" v-model="form.grau_parentesco" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_parentesco">Grau de parentesco</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-phone" />
                            <InputMask
                              id="f_parente_tel"
                              v-model="form.telefone_parente"
                              mask="(99) 99999-9999"
                              :unmask="false"
                              class="w-full"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_parente_tel">Telefone do parente</label>
                        </FloatLabel>
                      </div>
                    </div>

                    <div class="mt-4">
                      <Button
                        icon="pi pi-plus"
                        label="Adicionar mais parentes (em breve)"
                        severity="secondary"
                        outlined
                        disabled
                      />
                      <small class="mt-2 block text-xs text-surface-600 dark:text-surface-300">
                        Se você quiser, isso vira uma lista (1:N) depois.
                      </small>
                    </div>
                  </AccordionContent>
                </AccordionPanel>

                <!-- 3 -->
                <AccordionPanel value="3">
                  <AccordionHeader :ref="el => setPanelHeaderRef(el, 3)">4. Responsável</AccordionHeader>
                  <AccordionContent>
                    <div class="grid grid-cols-1 gap-4 xl:grid-cols-2">
                      <div class="xl:col-span-2">
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-user" />
                            <InputText id="f_resp_nome" v-model="form.nome_responsavel" class="w-full" variant="filled" />
                          </IconField>
                          <label for="f_resp_nome">Nome do responsável</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-id-card" />
                            <InputMask
                              id="f_resp_cpf"
                              v-model="form.cpf_responsavel"
                              mask="999.999.999-99"
                              :unmask="false"
                              class="w-full"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_resp_cpf">CPF do responsável</label>
                        </FloatLabel>
                      </div>

                      <div>
                        <FloatLabel variant="on">
                          <IconField>
                            <InputIcon class="pi pi-phone" />
                            <InputMask
                              id="f_resp_tel"
                              v-model="form.telefone_responsavel"
                              mask="(99) 99999-9999"
                              :unmask="false"
                              class="w-full"
                              variant="filled"
                            />
                          </IconField>
                          <label for="f_resp_tel">Telefone do responsável</label>
                        </FloatLabel>
                      </div>

                      <div class="xl:col-span-2">
                        <FloatLabel variant="on">
                          <Textarea id="f_resp_obs" v-model="form.observacao_responsavel" rows="3" class="w-full" variant="filled" />
                          <label for="f_resp_obs">Observações sobre o responsável</label>
                        </FloatLabel>
                      </div>

                      <div class="xl:col-span-2">
                        <div class="flex items-center gap-2">
                          <Checkbox inputId="f_bill" v-model="form.cobranca_no_responsavel" :binary="true" />
                          <label for="f_bill" class="text-sm text-surface-800 dark:text-surface-0">Cobrança no responsável</label>
                        </div>
                      </div>
                    </div>
                  </AccordionContent>
                </AccordionPanel>

                <!-- 4 -->
                <AccordionPanel value="4">
                  <AccordionHeader :ref="el => setPanelHeaderRef(el, 4)">5. Anotações internas</AccordionHeader>
                  <AccordionContent>
                    <div class="mb-3 text-xs text-surface-600 dark:text-surface-300">
                      Campo interno: não aparece no cadastro externo.
                    </div>

                    <FloatLabel variant="on">
                      <Textarea id="f_notas" v-model="form.notas_internas" rows="7" class="w-full" variant="filled" />
                      <label for="f_notas">Notas internas</label>
                    </FloatLabel>
                  </AccordionContent>
                </AccordionPanel>
              </Accordion>

              <div class="mt-4 flex justify-center">
                <Button
                  label="Salvar"
                  icon="pi pi-check"
                  :loading="saving"
                  @click="onSubmit"
                  class="min-w-[220px]"
                />
              </div>
            </main>
          </div>

          <!-- Dialog Criar Grupo -->
          <Dialog
            v-model:visible="createGroupDialog"
            modal
            :draggable="false"
            header="Criar grupo"
            :style="{ width: '26rem' }"
            :closable="!createGroupSaving"
            pt:mask:class="backdrop-blur-sm"
          >
            <span class="mb-6 block text-sm text-surface-600 dark:text-surface-300">
              Crie um grupo para organizar seus pacientes.
            </span>

            <div class="mb-4 flex items-center gap-4">
              <label for="group-name" class="w-24 text-sm font-semibold">Nome</label>
              <InputText id="group-name" v-model="newGroup.name" class="flex-auto" autocomplete="off" placeholder="Ex: Crianças" />
            </div>

            <div class="mb-6 flex items-center gap-4">
              <label class="w-24 text-sm font-semibold">Cor</label>
              <div class="flex flex-auto items-center gap-3">
                <input v-model="newGroup.color" type="color" class="h-9 w-12 cursor-pointer rounded-lg border border-surface-200 bg-transparent dark:border-surface-800" />
                <Chip :label="newGroup.color || '#—'" class="font-semibold" :style="{ backgroundColor: newGroup.color, color: '#fff' }" />
              </div>
            </div>

            <div v-if="createGroupError" class="mb-4 text-sm text-red-500">{{ createGroupError }}</div>

            <div class="flex justify-end gap-2">
              <Button label="Cancelar" severity="secondary" outlined :disabled="createGroupSaving" @click="createGroupDialog = false" />
              <Button label="Criar" icon="pi pi-check" :loading="createGroupSaving" @click="createGroupPersist" />
            </div>
          </Dialog>

          <!-- Dialog Criar Tag -->
          <Dialog
            v-model:visible="createTagDialog"
            modal
            :draggable="false"
            header="Criar tag"
            :style="{ width: '26rem' }"
            :closable="!createTagSaving"
            pt:mask:class="backdrop-blur-sm"
          >
            <span class="mb-6 block text-sm text-surface-600 dark:text-surface-300">
              Crie uma tag para facilitar filtros e organização.
            </span>

            <div class="mb-4 flex items-center gap-4">
              <label for="tag-name" class="w-24 text-sm font-semibold">Nome</label>
              <InputText id="tag-name" v-model="newTag.name" class="flex-auto" autocomplete="off" placeholder="Ex: Ansiedade" />
            </div>

            <div class="mb-6 flex items-center gap-4">
              <label class="w-24 text-sm font-semibold">Cor</label>
              <div class="flex flex-auto items-center gap-3">
                <input v-model="newTag.color" type="color" class="h-9 w-12 cursor-pointer rounded-lg border border-surface-200 bg-transparent dark:border-surface-800" />
                <Chip :label="newTag.color || '#—'" class="font-semibold" :style="{ backgroundColor: newTag.color, color: '#fff' }" />
              </div>
            </div>

            <div v-if="createTagError" class="mb-4 text-sm text-red-500">{{ createTagError }}</div>

            <div class="flex justify-end gap-2">
              <Button label="Cancelar" severity="secondary" outlined :disabled="createTagSaving" @click="createTagDialog = false" />
              <Button label="Criar" icon="pi pi-check" :loading="createTagSaving" @click="createTagPersist" />
            </div>
          </Dialog>
        </template>
      </Card>
    </div>
  </div>
</template>
