<!-- front-end/app/pages/gestao/prazos.vue -->
<script setup lang="ts">
const { apiFetch } = useApi()

interface ApiEdital {
  ID: string; Numero: string; Orgao: string; Modalidade: string
  Objeto: string; ValorEstimado: number; DataPublicacao: string
  DataAbertura: string; Status: string
}
interface ApiDocument {
  ID: string; Tipo: string; Nome: string
  DataVencimento: string | null; Observacoes: string
}
interface ApiContract {
  ID: string; Numero: string; Orgao: string; Objeto: string
  DataInicio: string; DataFim: string; Status: string
}

const { data: editais } = await useAsyncData('prazos-editais', () =>
  apiFetch<ApiEdital[]>('/editais'), { server: false }
)
const { data: documentos } = await useAsyncData('prazos-docs', () =>
  apiFetch<ApiDocument[]>('/documents'), { server: false }
)
const { data: contratos } = await useAsyncData('prazos-contratos', () =>
  apiFetch<ApiContract[]>('/contracts'), { server: false, default: () => [] }
)

// ---------- helpers ----------
const TIPO_DOC: Record<string, string> = {
  cnpj: 'CNPJ', contrato_social: 'Contrato Social', balanco: 'Balanço',
  certidao: 'Certidão', atestado: 'Atestado Técnico', procuracao: 'Procuração', outro: 'Outro',
}
const MODALIDADE: Record<string, string> = {
  pregao_eletronico: 'Pregão Eletrônico', pregao_presencial: 'Pregão Presencial',
  concorrencia: 'Concorrência', dispensa: 'Dispensa', inexigibilidade: 'Inexigibilidade',
}

function toDate(iso: string): Date {
  const [y, m, d] = iso.split('T')[0].split('-').map(Number)
  return new Date(y, m - 1, d)
}
function formatDate(iso: string): string {
  const [y, m, d] = iso.split('T')[0].split('-')
  return `${d}/${m}/${y}`
}
function diffDays(iso: string): number {
  const hoje = new Date()
  const hojeMs = Date.UTC(hoje.getFullYear(), hoje.getMonth(), hoje.getDate())
  const [y, m, d] = iso.split('T')[0].split('-').map(Number)
  const tMs = Date.UTC(y, m - 1, d)
  return Math.ceil((tMs - hojeMs) / (1000 * 60 * 60 * 24))
}
function diasLabel(diff: number): string {
  if (diff < 0) return `${Math.abs(diff)}d atrás`
  if (diff === 0) return 'Hoje'
  if (diff === 1) return 'Amanhã'
  return `em ${diff}d`
}

// ---------- prazo items ----------
interface PrazoItem {
  id: string
  titulo: string
  subtitulo: string
  dataIso: string
  diff: number
  tipo: 'edital' | 'documento' | 'contrato'
  link?: string
  icon: string
}

const tipoIcone: Record<string, string> = {
  edital: '📋', documento: '📄', contrato: '📝',
}
const tipoCor: Record<string, { color: string; bg: string }> = {
  edital:    { color: '#3b82f6', bg: '#eff6ff' },
  documento: { color: '#8b5cf6', bg: '#f5f3ff' },
  contrato:  { color: '#059669', bg: '#ecfdf5' },
}

const prazos = computed<PrazoItem[]>(() => {
  const items: PrazoItem[] = []

  // Editais — data de abertura (só status ativos)
  const statusAtivos = new Set(['em_analise', 'elaborando_proposta', 'edital_publicado', 'fase_lances', 'habilitacao', 'recurso'])
  for (const e of editais.value ?? []) {
    if (!statusAtivos.has(e.Status)) continue
    const d = diffDays(e.DataAbertura)
    items.push({
      id: `e-${e.ID}`,
      titulo: `Abertura — ${e.Numero}`,
      subtitulo: `${MODALIDADE[e.Modalidade] ?? e.Modalidade} · ${e.Orgao}`,
      dataIso: e.DataAbertura,
      diff: d,
      tipo: 'edital',
      link: `/oportunidades/${e.ID}`,
      icon: tipoIcone.edital,
    })
  }

  // Documentos — data de vencimento
  for (const doc of documentos.value ?? []) {
    if (!doc.DataVencimento) continue
    const d = diffDays(doc.DataVencimento)
    items.push({
      id: `d-${doc.ID}`,
      titulo: `Vencimento — ${doc.Nome || TIPO_DOC[doc.Tipo] || doc.Tipo}`,
      subtitulo: `${TIPO_DOC[doc.Tipo] || doc.Tipo}${doc.Observacoes ? ' · ' + doc.Observacoes : ''}`,
      dataIso: doc.DataVencimento,
      diff: d,
      tipo: 'documento',
      link: '/gestao/documentos',
      icon: tipoIcone.documento,
    })
  }

  // Contratos — data fim
  for (const c of contratos.value ?? []) {
    if (!c.DataFim || c.Status === 'encerrado') continue
    const d = diffDays(c.DataFim)
    items.push({
      id: `c-${c.ID}`,
      titulo: `Fim vigência — ${c.Numero}`,
      subtitulo: `Contrato · ${c.Orgao}`,
      dataIso: c.DataFim,
      diff: d,
      tipo: 'contrato',
      link: '/gestao/contratos',
      icon: tipoIcone.contrato,
    })
  }

  // Ordenar por data (mais próximo primeiro)
  items.sort((a, b) => a.diff - b.diff)
  return items
})

// ---------- filtros ----------
type FiltroTipo = 'todos' | 'edital' | 'documento' | 'contrato'
type FiltroPeriodo = 'todos' | 'vencido' | '7dias' | '30dias' | '90dias'

const filtroTipo = ref<FiltroTipo>('todos')
const filtroPeriodo = ref<FiltroPeriodo>('todos')

const filtroTipoOptions: { value: FiltroTipo; label: string }[] = [
  { value: 'todos', label: 'Todos' },
  { value: 'edital', label: 'Editais' },
  { value: 'documento', label: 'Documentos' },
  { value: 'contrato', label: 'Contratos' },
]
const filtroPeriodoOptions: { value: FiltroPeriodo; label: string }[] = [
  { value: 'todos', label: 'Todos' },
  { value: 'vencido', label: 'Vencidos' },
  { value: '7dias', label: 'Próx. 7 dias' },
  { value: '30dias', label: 'Próx. 30 dias' },
  { value: '90dias', label: 'Próx. 90 dias' },
]

const prazosFiltrados = computed(() => {
  return prazos.value.filter(p => {
    if (filtroTipo.value !== 'todos' && p.tipo !== filtroTipo.value) return false
    if (filtroPeriodo.value === 'vencido' && p.diff >= 0) return false
    if (filtroPeriodo.value === '7dias' && (p.diff < 0 || p.diff > 7)) return false
    if (filtroPeriodo.value === '30dias' && (p.diff < 0 || p.diff > 30)) return false
    if (filtroPeriodo.value === '90dias' && (p.diff < 0 || p.diff > 90)) return false
    return true
  })
})

// ---------- stats ----------
const stats = computed(() => {
  const all = prazos.value
  return {
    total: all.length,
    vencidos: all.filter(p => p.diff < 0).length,
    hoje: all.filter(p => p.diff === 0).length,
    semana: all.filter(p => p.diff > 0 && p.diff <= 7).length,
    mes: all.filter(p => p.diff > 0 && p.diff <= 30).length,
  }
})

function urgencia(diff: number): 'vencido' | 'critico' | 'urgente' | 'normal' | 'folgado' {
  if (diff < 0) return 'vencido'
  if (diff === 0) return 'critico'
  if (diff <= 7) return 'urgente'
  if (diff <= 30) return 'normal'
  return 'folgado'
}
const urgenciaCfg = {
  vencido: { label: 'Vencido',  color: '#dc2626', bg: '#fef2f2', border: '#fecaca' },
  critico: { label: 'Hoje',     color: '#dc2626', bg: '#fef2f2', border: '#fecaca' },
  urgente: { label: 'Urgente',  color: '#ea580c', bg: '#fff7ed', border: '#fed7aa' },
  normal:  { label: 'Normal',   color: '#d97706', bg: '#fffbeb', border: '#fde68a' },
  folgado: { label: 'Folgado',  color: '#16a34a', bg: '#f0fdf4', border: '#bbf7d0' },
}
</script>

<template>
  <div class="page">
    <AppTopbar title="Prazos" breadcrumb="Gestão · Prazos" />

    <div class="content">
      <!-- Stats cards -->
      <div class="stats-row">
        <div class="stat-card stat-danger" @click="filtroPeriodo = 'vencido'; filtroTipo = 'todos'">
          <span class="stat-num">{{ stats.vencidos }}</span>
          <span class="stat-label">Vencidos</span>
        </div>
        <div class="stat-card stat-critical" @click="filtroPeriodo = 'todos'; filtroTipo = 'todos'">
          <span class="stat-num">{{ stats.hoje }}</span>
          <span class="stat-label">Hoje</span>
        </div>
        <div class="stat-card stat-warning" @click="filtroPeriodo = '7dias'; filtroTipo = 'todos'">
          <span class="stat-num">{{ stats.semana }}</span>
          <span class="stat-label">Próx. 7 dias</span>
        </div>
        <div class="stat-card stat-info" @click="filtroPeriodo = '30dias'; filtroTipo = 'todos'">
          <span class="stat-num">{{ stats.mes }}</span>
          <span class="stat-label">Próx. 30 dias</span>
        </div>
        <div class="stat-card stat-total">
          <span class="stat-num">{{ stats.total }}</span>
          <span class="stat-label">Total</span>
        </div>
      </div>

      <!-- Filters -->
      <div class="filters-row">
        <div class="filter-group">
          <button
            v-for="opt in filtroTipoOptions" :key="opt.value"
            class="filter-btn"
            :class="{ active: filtroTipo === opt.value }"
            @click="filtroTipo = opt.value"
          >{{ opt.label }}</button>
        </div>
        <div class="filter-group">
          <button
            v-for="opt in filtroPeriodoOptions" :key="opt.value"
            class="filter-btn"
            :class="{ active: filtroPeriodo === opt.value }"
            @click="filtroPeriodo = opt.value"
          >{{ opt.label }}</button>
        </div>
      </div>

      <!-- Timeline -->
      <div class="timeline-card">
        <div v-if="prazosFiltrados.length === 0" class="timeline-empty">
          <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#cbd5e1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
          <p>Nenhum prazo encontrado para os filtros selecionados.</p>
        </div>

        <NuxtLink
          v-for="(prazo, idx) in prazosFiltrados"
          :key="prazo.id"
          :to="prazo.link ?? '#'"
          class="timeline-item"
          :class="urgencia(prazo.diff)"
        >
          <div class="tl-left">
            <div class="tl-dot" :style="{ background: urgenciaCfg[urgencia(prazo.diff)].color }" />
            <div v-if="idx < prazosFiltrados.length - 1" class="tl-line" />
          </div>

          <div class="tl-content">
            <div class="tl-header">
              <div class="tl-icon-badge" :style="{ background: tipoCor[prazo.tipo].bg, color: tipoCor[prazo.tipo].color }">
                {{ prazo.icon }}
              </div>
              <div class="tl-title-area">
                <span class="tl-title">{{ prazo.titulo }}</span>
                <span class="tl-sub">{{ prazo.subtitulo }}</span>
              </div>
              <div class="tl-right-area">
                <span
                  class="tl-urgencia"
                  :style="{
                    color: urgenciaCfg[urgencia(prazo.diff)].color,
                    background: urgenciaCfg[urgencia(prazo.diff)].bg,
                    borderColor: urgenciaCfg[urgencia(prazo.diff)].border,
                  }"
                >{{ urgenciaCfg[urgencia(prazo.diff)].label }}</span>
                <span class="tl-date">{{ formatDate(prazo.dataIso) }}</span>
                <span class="tl-diff" :style="{ color: urgenciaCfg[urgencia(prazo.diff)].color }">
                  {{ diasLabel(prazo.diff) }}
                </span>
              </div>
            </div>
          </div>
        </NuxtLink>
      </div>
    </div>
  </div>
</template>

<style scoped>
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,300..700&family=JetBrains+Mono:wght@400;600&display=swap');

.page { display: flex; flex-direction: column; height: 100vh; font-family: 'DM Sans', system-ui, sans-serif; }
.content { padding: 24px 28px 40px; flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 18px; }

/* ── Stats ── */
.stats-row { display: flex; gap: 12px; }
.stat-card {
  flex: 1; background: white; border-radius: 12px;
  border: 1px solid #e2e8f0; padding: 16px 18px;
  display: flex; flex-direction: column; gap: 4px;
  cursor: pointer; transition: all .15s;
  box-shadow: 0 1px 3px rgba(0,0,0,.04);
}
.stat-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,.08); }
.stat-num { font-size: 28px; font-weight: 800; font-family: 'JetBrains Mono', monospace; line-height: 1; }
.stat-label { font-size: 11.5px; font-weight: 600; color: #94a3b8; text-transform: uppercase; letter-spacing: .5px; }
.stat-danger .stat-num { color: #dc2626; }
.stat-danger { border-left: 3px solid #dc2626; }
.stat-critical .stat-num { color: #ea580c; }
.stat-critical { border-left: 3px solid #ea580c; }
.stat-warning .stat-num { color: #d97706; }
.stat-warning { border-left: 3px solid #d97706; }
.stat-info .stat-num { color: #3b82f6; }
.stat-info { border-left: 3px solid #3b82f6; }
.stat-total .stat-num { color: #0f172a; }
.stat-total { border-left: 3px solid #667eea; }

/* ── Filters ── */
.filters-row { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
.filter-group { display: flex; gap: 4px; background: #f1f5f9; border-radius: 9px; padding: 3px; }
.filter-btn {
  padding: 6px 14px; border-radius: 7px; border: none;
  font-size: 12px; font-weight: 600; cursor: pointer;
  color: #64748b; background: transparent; transition: all .15s;
}
.filter-btn:hover { color: #334155; }
.filter-btn.active { background: white; color: #0f172a; box-shadow: 0 1px 3px rgba(0,0,0,.08); }

/* ── Timeline ── */
.timeline-card {
  background: white; border-radius: 14px;
  border: 1px solid #e2e8f0; overflow: hidden;
  box-shadow: 0 1px 3px rgba(0,0,0,.04);
}
.timeline-empty {
  display: flex; flex-direction: column; align-items: center;
  gap: 10px; padding: 48px 20px; color: #94a3b8;
}
.timeline-empty p { font-size: 13px; margin: 0; }

.timeline-item {
  display: flex; gap: 0; text-decoration: none;
  transition: background .12s;
}
.timeline-item:hover { background: #fafbfd; }
.timeline-item:not(:last-child) { border-bottom: 1px solid #f5f7fa; }

/* Urgency left accent */
.timeline-item.vencido { border-left: 3px solid #dc2626; }
.timeline-item.critico { border-left: 3px solid #dc2626; }
.timeline-item.urgente { border-left: 3px solid #ea580c; }
.timeline-item.normal  { border-left: 3px solid #d97706; }
.timeline-item.folgado { border-left: 3px solid #16a34a; }

/* Timeline dots + line */
.tl-left {
  width: 32px; display: flex; flex-direction: column;
  align-items: center; padding-top: 22px; flex-shrink: 0;
}
.tl-dot {
  width: 10px; height: 10px; border-radius: 50%;
  flex-shrink: 0; position: relative; z-index: 1;
}
.tl-line {
  width: 2px; flex: 1; background: #e9edf3; margin-top: 4px;
}

/* Content */
.tl-content { flex: 1; padding: 14px 18px 14px 6px; min-width: 0; }
.tl-header { display: flex; align-items: center; gap: 12px; }
.tl-icon-badge {
  width: 36px; height: 36px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; flex-shrink: 0;
}
.tl-title-area { flex: 1; min-width: 0; }
.tl-title {
  display: block; font-size: 13.5px; font-weight: 700; color: #0f172a;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tl-sub {
  display: block; font-size: 12px; color: #94a3b8; margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tl-right-area {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: 3px; flex-shrink: 0;
}
.tl-urgencia {
  font-size: 10.5px; font-weight: 700; padding: 2px 9px;
  border-radius: 20px; border: 1px solid;
}
.tl-date {
  font-size: 12px; font-weight: 600; color: #475569;
  font-family: 'JetBrains Mono', monospace;
}
.tl-diff { font-size: 11px; font-weight: 700; }

/* ── Responsive ── */
@media (max-width: 768px) {
  .stats-row { flex-wrap: wrap; }
  .stat-card { min-width: calc(50% - 8px); }
  .filters-row { flex-direction: column; }
  .tl-header { flex-wrap: wrap; }
  .tl-right-area { flex-direction: row; gap: 8px; align-items: center; }
}
</style>
