'use client';

import { Fragment, useState } from 'react';
import { useOpiniones, useConsultarOpinion, useDescargarPdf } from '@/lib/hooks/use-documentos';
import {
  useDeclaraciones,
  useCreateDeclaracion,
  useUploadComprobantePago,
  useDeleteDeclaracion,
  useDownloadDeclaracionPdf,
} from '@/lib/hooks/use-declaraciones';
import { fileToBase64, type Declaracion, type Impuesto, type Periodicidad } from '@/lib/api/declaraciones';
import { useConstancias, useConsultarConstancia, useDescargarConstanciaPdf } from '@/lib/hooks/use-constancias';
import type { Constancia } from '@/lib/api/constancias';
import { useAuthStore } from '@/stores/auth-store';
import { useContribuyenteStore } from '@/stores/contribuyente-store';
import { Header } from '@/components/layouts/header';
import { Card, CardContent, Button, Tabs, TabsList, TabsTrigger, TabsContent, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Input, Label } from '@horux/shared-ui';
import {
  FileCheck, Download, RefreshCw, Loader2, AlertTriangle, CheckCircle2, XCircle, Clock,
  IdCard, FileText, Upload, Plus, Trash2, Receipt, FolderOpen, Tag, Briefcase,
} from 'lucide-react';
import { PapeleriaTab } from '@/components/documentos/papeleria-tab';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import * as docsApi from '@/lib/api/documentos';

const MESES = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
const IMPUESTOS: Impuesto[] = ['IVA', 'ISR', 'IEPS', 'SUELDOS', 'DIOT', 'OTRO'];
const PERIODICIDADES: { value: Periodicidad; label: string }[] = [
  { value: 'mensual', label: 'Mensual' },
  { value: 'bimestral', label: 'Bimestral' },
  { value: 'trimestral', label: 'Trimestral' },
  { value: 'semestral', label: 'Semestral' },
  { value: 'anual', label: 'Anual' },
];
const PERIODICIDAD_LABELS: Record<string, string> = {
  mensual: 'Mensual', bimestral: 'Bimestral', trimestral: 'Trimestral',
  semestral: 'Semestral', anual: 'Anual',
};

/** Returns period options based on periodicidad. Each option has a value (mes start) and a label. */
function getPeriodOptions(periodicidad: Periodicidad): { value: number; label: string }[] {
  switch (periodicidad) {
    case 'mensual':
      return MESES.map((m, i) => ({ value: i + 1, label: m }));
    case 'bimestral':
      return [
        { value: 1, label: 'Enero – Febrero' },
        { value: 3, label: 'Marzo – Abril' },
        { value: 5, label: 'Mayo – Junio' },
        { value: 7, label: 'Julio – Agosto' },
        { value: 9, label: 'Septiembre – Octubre' },
        { value: 11, label: 'Noviembre – Diciembre' },
      ];
    case 'trimestral':
      return [
        { value: 1, label: 'Enero – Marzo' },
        { value: 4, label: 'Abril – Junio' },
        { value: 7, label: 'Julio – Septiembre' },
        { value: 10, label: 'Octubre – Diciembre' },
      ];
    case 'semestral':
      return [
        { value: 1, label: 'Enero – Junio' },
        { value: 7, label: 'Julio – Diciembre' },
      ];
    case 'anual':
      return [{ value: 1, label: 'Anual' }];
    default:
      return MESES.map((m, i) => ({ value: i + 1, label: m }));
  }
}

/** Returns a display label for a period (mes) given its periodicidad */
function getPeriodLabel(periodicidad: string, mes: number): string {
  const options = getPeriodOptions(periodicidad as Periodicidad);
  return options.find(o => o.value === mes)?.label || MESES[mes - 1] || String(mes);
}
const ROLES_UPLOAD = ['owner', 'cfo', 'contador', 'auxiliar'];

function EstatusBadge({ estatus }: { estatus: string }) {
  if (estatus === 'Positiva') return <span className="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400"><CheckCircle2 className="h-3 w-3" /> {estatus}</span>;
  if (estatus === 'Negativa') return <span className="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400"><XCircle className="h-3 w-3" /> {estatus}</span>;
  return <span className="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400"><AlertTriangle className="h-3 w-3" /> {estatus}</span>;
}

export default function DocumentosPage() {
  const user = useAuthStore((s) => s.user);
  const canConsultarOpinion = user?.role === 'owner' || user?.role === 'cfo';
  const canSeePapeleria = user?.role !== 'cliente';

  return (
    <>
      <Header title="Documentos" />
      <main className="p-6">
        <Tabs defaultValue="declaraciones" className="space-y-4">
          <TabsList>
            <TabsTrigger value="opinion"><FileCheck className="h-4 w-4 mr-1.5" /> Opinión de Cumplimiento</TabsTrigger>
            <TabsTrigger value="constancia"><IdCard className="h-4 w-4 mr-1.5" /> Constancia de Situación Fiscal</TabsTrigger>
            <TabsTrigger value="declaraciones"><FileText className="h-4 w-4 mr-1.5" /> Declaraciones</TabsTrigger>
            <TabsTrigger value="extras"><FolderOpen className="h-4 w-4 mr-1.5" /> Extras</TabsTrigger>
            {canSeePapeleria && (
              <TabsTrigger value="papeleria"><Briefcase className="h-4 w-4 mr-1.5" /> Papelería de Trabajo</TabsTrigger>
            )}
          </TabsList>
          <TabsContent value="opinion"><OpinionTab canConsultar={canConsultarOpinion} /></TabsContent>
          <TabsContent value="constancia"><ConstanciaTab /></TabsContent>
          <TabsContent value="declaraciones"><DeclaracionesTab /></TabsContent>
          <TabsContent value="extras"><ExtrasTab /></TabsContent>
          {canSeePapeleria && (
            <TabsContent value="papeleria"><PapeleriaTab /></TabsContent>
          )}
        </Tabs>
      </main>
    </>
  );
}

// ============================================================================
// Opinión de Cumplimiento
// ============================================================================
function OpinionTab({ canConsultar }: { canConsultar: boolean }) {
  const { data: opiniones, isLoading, error } = useOpiniones();
  const consultar = useConsultarOpinion();
  const descargar = useDescargarPdf();

  return (
    <Card>
      <CardContent className="pt-6">
        <div className="flex items-center justify-between mb-4">
          <h2 className="text-lg font-semibold flex items-center gap-2"><FileCheck className="h-5 w-5" /> Opinión de Cumplimiento</h2>
          {canConsultar && (
            <Button onClick={() => consultar.mutate()} disabled={consultar.isPending} size="sm">
              {consultar.isPending ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Consultando...</> : <><RefreshCw className="h-4 w-4 mr-2" /> Consultar ahora</>}
            </Button>
          )}
        </div>
        {consultar.isError && <div className="p-3 mb-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">Error: {(consultar.error as Error).message}</div>}
        {isLoading && <div className="flex items-center justify-center py-12"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>}
        {error && <div className="p-4 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">Error al cargar opiniones: {(error as Error).message}</div>}
        {!isLoading && !error && opiniones?.length === 0 && (
          <div className="text-center py-12 text-muted-foreground">
            <FileCheck className="h-12 w-12 mx-auto mb-3 opacity-30" />
            <p>No hay opiniones registradas.</p>
            <p className="text-sm mt-1">La consulta automática se ejecuta cada semana.</p>
          </div>
        )}
        {!isLoading && opiniones && opiniones.length > 0 && (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b text-left text-muted-foreground">
                  <th className="pb-2 font-medium">Fecha de consulta</th>
                  <th className="pb-2 font-medium">Estatus</th>
                  <th className="pb-2 font-medium">Folio</th>
                  <th className="pb-2 font-medium">RFC</th>
                  <th className="pb-2 font-medium text-right">PDF</th>
                </tr>
              </thead>
              <tbody className="divide-y">
                {opiniones.map((op) => (
                  <tr key={op.id} className="hover:bg-muted/50">
                    <td className="py-3"><div className="flex items-center gap-2"><Clock className="h-4 w-4 text-muted-foreground" />{new Date(op.fechaConsulta).toLocaleDateString('es-MX', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}</div></td>
                    <td className="py-3"><EstatusBadge estatus={op.estatus} /></td>
                    <td className="py-3 font-mono text-xs">{op.folio}</td>
                    <td className="py-3 font-mono text-xs">{op.rfc}</td>
                    <td className="py-3 text-right"><Button variant="ghost" size="sm" onClick={() => descargar.mutate(op.id)} disabled={descargar.isPending}><Download className="h-3.5 w-3.5 mr-1" /> Descargar</Button></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </CardContent>
    </Card>
  );
}

// ============================================================================
// Constancia de Situación Fiscal
// ============================================================================
function ConstanciaTab() {
  const user = useAuthStore((s) => s.user);
  const canConsultar = user?.role === 'owner' || user?.role === 'cfo';
  const { data: constancias, isLoading, error } = useConstancias();
  const consultar = useConsultarConstancia();
  const descargar = useDescargarConstanciaPdf();
  const [expandedId, setExpandedId] = useState<number | null>(null);

  const latest = constancias?.[0];

  return (
    <div className="space-y-4">
      <Card>
        <CardContent className="pt-6">
          <div className="flex items-center justify-between mb-4 gap-2 flex-wrap">
            <div>
              <h2 className="text-lg font-semibold flex items-center gap-2"><IdCard className="h-5 w-5" /> Constancia de Situación Fiscal</h2>
              <p className="text-sm text-muted-foreground mt-0.5">Descarga mensual automática del SAT el día 1. También se actualizan el domicilio fiscal y los regímenes activos del tenant.</p>
            </div>
            {canConsultar && (
              <Button onClick={() => consultar.mutate()} disabled={consultar.isPending} size="sm">
                {consultar.isPending ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Consultando...</> : <><RefreshCw className="h-4 w-4 mr-2" /> Consultar ahora</>}
              </Button>
            )}
          </div>
          {consultar.isError && <div className="p-3 mb-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">Error: {(consultar.error as Error).message}</div>}

          {isLoading && <div className="flex items-center justify-center py-12"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>}
          {error && <div className="p-4 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">Error: {(error as Error).message}</div>}

          {!isLoading && !error && constancias?.length === 0 && (
            <div className="text-center py-12 text-muted-foreground">
              <IdCard className="h-12 w-12 mx-auto mb-3 opacity-30" />
              <p>No hay constancias registradas.</p>
              <p className="text-sm mt-1">La consulta automática se ejecuta el 1° de cada mes.</p>
            </div>
          )}

          {latest && (
            <ConstanciaDetalle datos={latest.datos} />
          )}
        </CardContent>
      </Card>

      {constancias && constancias.length > 0 && (
        <Card>
          <CardContent className="pt-6">
            <h3 className="text-md font-semibold mb-3">Historial (últimas {constancias.length})</h3>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="border-b text-left text-muted-foreground">
                    <th className="pb-2 pr-2 font-medium">Fecha de consulta</th>
                    <th className="pb-2 pr-2 font-medium">Estatus</th>
                    <th className="pb-2 pr-2 font-medium">RFC</th>
                    <th className="pb-2 pr-2 font-medium">Régimenes activos</th>
                    <th className="pb-2 pr-2 font-medium text-right">Acciones</th>
                  </tr>
                </thead>
                <tbody className="divide-y">
                  {constancias.map((c) => {
                    const activos = c.datos.regimenes.filter(r => !r.fechaFin).length;
                    const expanded = expandedId === c.id;
                    return (
                      <Fragment key={c.id}>
                        <tr className="hover:bg-muted/50">
                          <td className="py-3 pr-2"><div className="flex items-center gap-2"><Clock className="h-4 w-4 text-muted-foreground" />{new Date(c.fechaConsulta).toLocaleDateString('es-MX', { year: 'numeric', month: 'long', day: 'numeric' })}</div></td>
                          <td className="py-3 pr-2">
                            <span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium ${c.estatusPadron === 'ACTIVO' ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400'}`}>
                              {c.estatusPadron || '—'}
                            </span>
                          </td>
                          <td className="py-3 pr-2 font-mono text-xs">{c.rfc}</td>
                          <td className="py-3 pr-2 text-xs">{activos}</td>
                          <td className="py-3 pr-2 text-right">
                            <Button variant="ghost" size="sm" onClick={() => setExpandedId(expanded ? null : c.id)}>
                              {expanded ? 'Ocultar' : 'Ver datos'}
                            </Button>
                            <Button variant="ghost" size="sm" onClick={() => descargar.mutate(c.id)} disabled={descargar.isPending}>
                              <Download className="h-3.5 w-3.5 mr-1" /> PDF
                            </Button>
                          </td>
                        </tr>
                        {expanded && (
                          <tr><td colSpan={5} className="p-0 bg-muted/30"><div className="p-4"><ConstanciaDetalle datos={c.datos} /></div></td></tr>
                        )}
                      </Fragment>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
}

function ConstanciaDetalle({ datos }: { datos: Constancia['datos'] }) {
  const d = datos.domicilio;
  const domicilio = [
    [d.tipoVialidad, d.nombreVialidad].filter(Boolean).join(' '),
    d.numeroExterior && `Ext. ${d.numeroExterior}`,
    d.numeroInterior && d.numeroInterior.toUpperCase() !== 'SIN NUMERO' && `Int. ${d.numeroInterior}`,
    d.colonia,
    [d.codigoPostal, d.localidad].filter(Boolean).join(' '),
    [d.municipio, d.entidadFederativa].filter(Boolean).join(', '),
  ].filter(Boolean).join(' · ');

  const regimenesActivos = datos.regimenes.filter(r => !r.fechaFin);

  return (
    <div className="grid md:grid-cols-2 gap-4 text-sm">
      <div>
        <h4 className="text-xs font-semibold uppercase text-muted-foreground mb-2">Identificación</h4>
        <dl className="space-y-1">
          <div className="flex justify-between gap-2"><dt className="text-muted-foreground">RFC</dt><dd className="font-mono">{datos.rfc}</dd></div>
          {datos.curp && <div className="flex justify-between gap-2"><dt className="text-muted-foreground">CURP</dt><dd className="font-mono">{datos.curp}</dd></div>}
          {datos.razonSocial && <div className="flex justify-between gap-2"><dt className="text-muted-foreground">Razón social</dt><dd className="text-right">{datos.razonSocial}</dd></div>}
          {!datos.razonSocial && (datos.nombre || datos.primerApellido) && (
            <div className="flex justify-between gap-2"><dt className="text-muted-foreground">Nombre</dt><dd className="text-right">{[datos.nombre, datos.primerApellido, datos.segundoApellido].filter(Boolean).join(' ')}</dd></div>
          )}
          <div className="flex justify-between gap-2"><dt className="text-muted-foreground">Estatus</dt><dd>{datos.estatusPadron}</dd></div>
          <div className="flex justify-between gap-2"><dt className="text-muted-foreground">Inicio de operaciones</dt><dd>{datos.fechaInicioOperaciones}</dd></div>
        </dl>
      </div>
      <div>
        <h4 className="text-xs font-semibold uppercase text-muted-foreground mb-2">Domicilio fiscal</h4>
        <p>{domicilio || '—'}</p>
      </div>
      <div className="md:col-span-2">
        <h4 className="text-xs font-semibold uppercase text-muted-foreground mb-2">Regímenes activos ({regimenesActivos.length})</h4>
        {regimenesActivos.length === 0 ? (
          <p className="text-muted-foreground">Sin regímenes activos</p>
        ) : (
          <ul className="space-y-1">
            {regimenesActivos.map((r, i) => (
              <li key={i} className="flex justify-between gap-2">
                <span>{r.nombre}</span>
                <span className="text-xs text-muted-foreground">desde {r.fechaInicio}</span>
              </li>
            ))}
          </ul>
        )}
      </div>
      {datos.obligaciones.length > 0 && (
        <div className="md:col-span-2">
          <h4 className="text-xs font-semibold uppercase text-muted-foreground mb-2">Obligaciones ({datos.obligaciones.filter(o => !o.fechaFin).length} activas)</h4>
          <ul className="space-y-1">
            {datos.obligaciones.filter(o => !o.fechaFin).map((o, i) => (
              <li key={i} className="text-xs">
                <span className="font-medium">{o.descripcion}</span>
                <span className="text-muted-foreground"> — {o.descripcionVencimiento}</span>
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

// ============================================================================
// Declaraciones
// ============================================================================
function DeclaracionesTab() {
  const user = useAuthStore((s) => s.user);
  const canUpload = !!user?.role && ROLES_UPLOAD.includes(user.role);
  const { selectedContribuyenteId } = useContribuyenteStore();

  // Default: current month range
  const now = new Date();
  const y = now.getFullYear();
  const m = now.getMonth() + 1;
  const lastDay = new Date(y, m, 0).getDate();
  const [fechaDesde, setFechaDesde] = useState(`${y}-${String(m).padStart(2, '0')}-01`);
  const [fechaHasta, setFechaHasta] = useState(`${y}-${String(m).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`);

  const [uploadOpen, setUploadOpen] = useState(false);
  const [pagoDeclaracion, setPagoDeclaracion] = useState<Declaracion | null>(null);

  const { data: declaraciones, isLoading, error } = useDeclaraciones(fechaDesde, fechaHasta, selectedContribuyenteId);
  const deleteDecl = useDeleteDeclaracion();
  const downloadPdf = useDownloadDeclaracionPdf();

  return (
    <Card>
      <CardContent className="pt-6">
        <div className="flex items-center justify-between mb-4 gap-2 flex-wrap">
          <div>
            <h2 className="text-lg font-semibold flex items-center gap-2"><FileText className="h-5 w-5" /> Declaraciones</h2>
            <p className="text-sm text-muted-foreground mt-0.5">Sube el PDF de cada declaración y su comprobante de pago. Al subirla, se desactivan los recordatorios correspondientes.</p>
          </div>
          {canUpload && <Button size="sm" onClick={() => setUploadOpen(true)}><Plus className="h-4 w-4 mr-1.5" /> Subir declaración</Button>}
        </div>

        <div className="flex flex-wrap items-end gap-3 mb-4 pb-3 border-b">
          <div className="flex items-center gap-2">
            <label className="text-xs text-muted-foreground">Desde</label>
            <Input type="date" value={fechaDesde} onChange={(e) => setFechaDesde(e.target.value)} className="h-8 w-[150px] text-sm" />
          </div>
          <div className="flex items-center gap-2">
            <label className="text-xs text-muted-foreground">Hasta</label>
            <Input type="date" value={fechaHasta} onChange={(e) => setFechaHasta(e.target.value)} className="h-8 w-[150px] text-sm" />
          </div>
        </div>

        {isLoading && <div className="flex items-center justify-center py-12"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>}
        {error && <div className="p-4 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">Error: {(error as Error).message}</div>}

        {!isLoading && !error && declaraciones && declaraciones.length === 0 && (
          <div className="text-center py-12 text-muted-foreground">
            <FileText className="h-12 w-12 mx-auto mb-3 opacity-30" />
            <p>No hay declaraciones en el rango seleccionado.</p>
            {canUpload && <p className="text-sm mt-1">Usa el botón "Subir declaración" para cargar la primera.</p>}
          </div>
        )}

        {!isLoading && declaraciones && declaraciones.length > 0 && (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b text-left text-muted-foreground">
                  <th className="pb-2 pr-2 font-medium">Periodo</th>
                  <th className="pb-2 pr-2 font-medium">Tipo</th>
                  <th className="pb-2 pr-2 font-medium">Impuestos</th>
                  <th className="pb-2 pr-2 font-medium text-right">Monto</th>
                  <th className="pb-2 pr-2 font-medium">Declaración</th>
                  <th className="pb-2 pr-2 font-medium">Pago</th>
                  <th className="pb-2 pr-2 font-medium">Fecha subida</th>
                  <th className="pb-2 pr-2 font-medium text-right">Acciones</th>
                </tr>
              </thead>
              <tbody className="divide-y">
                {declaraciones.map((d) => {
                  const isPaidByAmount = d.montoPago === 0;
                  const isPaid = d.tienePagoPdf || isPaidByAmount;
                  return (
                  <tr key={d.id} className="hover:bg-muted/50">
                    <td className="py-3 pr-2 font-medium">{getPeriodLabel(d.periodicidad, d.mes)} {d.año}</td>
                    <td className="py-3 pr-2">
                      <span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${d.tipo === 'normal' ? 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400' : 'bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400'}`}>
                        {d.tipo === 'normal' ? 'Normal' : 'Complementaria'}
                      </span>
                    </td>
                    <td className="py-3 pr-2">
                      <div className="flex flex-wrap gap-1">
                        {d.impuestos.map(i => <span key={i} className="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-muted">{i}</span>)}
                      </div>
                    </td>
                    <td className="py-3 pr-2 text-right font-mono text-sm">
                      {d.montoPago != null ? `$${d.montoPago.toLocaleString('es-MX', { minimumFractionDigits: 2 })}` : '—'}
                    </td>
                    <td className="py-3 pr-2">
                      <div className="flex flex-col gap-1">
                        {d.pdfFilename && (
                          <button onClick={() => downloadPdf.mutate({ id: d.id, variant: 'declaracion', filename: d.pdfFilename! })} className="inline-flex items-center gap-1 text-xs text-primary hover:underline">
                            <Download className="h-3 w-3" /> Declaración
                          </button>
                        )}
                        {d.tieneLigaPago && (
                          <button onClick={() => downloadPdf.mutate({ id: d.id, variant: 'liga', filename: d.ligaPagoFilename || `liga-pago-${d.id}.pdf` })} className="inline-flex items-center gap-1 text-xs text-primary hover:underline">
                            <Download className="h-3 w-3" /> Liga de pago
                          </button>
                        )}
                      </div>
                    </td>
                    <td className="py-3 pr-2">
                      {d.tienePagoPdf ? (
                        <button onClick={() => downloadPdf.mutate({ id: d.id, variant: 'pago', filename: d.pdfPagoFilename || `pago-${d.id}.pdf` })} className="inline-flex items-center gap-1 text-xs text-green-700 dark:text-green-400 hover:underline">
                          <CheckCircle2 className="h-3 w-3" /> Pagado
                        </button>
                      ) : isPaidByAmount ? (
                        <span className="inline-flex items-center gap-1 text-xs text-green-700 dark:text-green-400">
                          <CheckCircle2 className="h-3 w-3" /> $0 — Sin pago
                        </span>
                      ) : (
                        <span className="text-xs text-muted-foreground">Sin comprobante</span>
                      )}
                    </td>
                    <td className="py-3 pr-2 text-xs text-muted-foreground">
                      {new Date(d.createdAt).toLocaleDateString('es-MX', { day: '2-digit', month: 'short', year: 'numeric' })}
                    </td>
                    <td className="py-3 pr-2">
                      <div className="flex items-center justify-end gap-1">
                        {canUpload && !isPaid && (
                          <Button variant="ghost" size="sm" onClick={() => setPagoDeclaracion(d)} title="Subir comprobante de pago">
                            <Receipt className="h-3.5 w-3.5" />
                          </Button>
                        )}
                        {canUpload && (
                          <Button variant="ghost" size="sm" onClick={() => { if (confirm('¿Eliminar esta declaración?')) deleteDecl.mutate(d.id); }} title="Eliminar">
                            <Trash2 className="h-3.5 w-3.5 text-red-600" />
                          </Button>
                        )}
                      </div>
                    </td>
                  </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
      </CardContent>

      {uploadOpen && <UploadDialog onClose={() => setUploadOpen(false)} />}
      {pagoDeclaracion && <ComprobantePagoDialog declaracion={pagoDeclaracion} onClose={() => setPagoDeclaracion(null)} />}
    </Card>
  );
}

// ============================================================================
// Upload Dialog
// ============================================================================
function UploadDialog({ onClose }: { onClose: () => void }) {
  const create = useCreateDeclaracion();
  const { selectedContribuyenteId } = useContribuyenteStore();
  const currentYear = new Date().getFullYear();
  const [año, setAño] = useState(currentYear);
  const [mes, setMes] = useState(new Date().getMonth() + 1);
  const [tipo, setTipo] = useState<'normal' | 'complementaria'>('normal');
  const [periodicidad, setPeriodicidad] = useState<Periodicidad>('mensual');
  const yearsOptions = Array.from({ length: 6 }, (_, i) => currentYear - i);
  const [impuestos, setImpuestos] = useState<Impuesto[]>([]);
  const [montoPago, setMontoPago] = useState('');
  const [file, setFile] = useState<File | null>(null);
  const [ligaFile, setLigaFile] = useState<File | null>(null);
  const [notas, setNotas] = useState('');
  const [err, setErr] = useState<string | null>(null);

  const periodOptions = getPeriodOptions(periodicidad);

  const handlePeriodicidadChange = (p: Periodicidad) => {
    setPeriodicidad(p);
    // Reset mes to first valid option for the new periodicidad
    const opts = getPeriodOptions(p);
    if (!opts.find(o => o.value === mes)) {
      setMes(opts[0].value);
    }
  };

  const toggleImpuesto = (i: Impuesto) => {
    setImpuestos(prev => prev.includes(i) ? prev.filter(x => x !== i) : [...prev, i]);
  };

  const submit = async (e: React.FormEvent) => {
    e.preventDefault();
    setErr(null);
    if (!file) return setErr('Selecciona el PDF de la declaración');
    if (impuestos.length === 0) return setErr('Selecciona al menos un impuesto');
    try {
      const pdfBase64 = await fileToBase64(file);
      const ligaPagoBase64 = ligaFile ? await fileToBase64(ligaFile) : undefined;
      const montoNum = montoPago.trim() !== '' ? parseFloat(montoPago) : undefined;
      await create.mutateAsync({
        año, mes, tipo, periodicidad, impuestos,
        montoPago: montoNum,
        pdfBase64, pdfFilename: file.name,
        ligaPagoBase64,
        ligaPagoFilename: ligaFile?.name,
        notas: notas.trim() || undefined,
        contribuyenteId: selectedContribuyenteId || undefined,
      });
      onClose();
    } catch (e: any) {
      setErr(e?.response?.data?.message || e?.message || 'Error al subir');
    }
  };

  return (
    <Dialog open onOpenChange={(o) => { if (!o) onClose(); }}>
      <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Subir declaración</DialogTitle>
          <DialogDescription>
            Al subir se marcarán como resueltos los recordatorios de declaración correspondientes. Si es complementaria, también los de pago.
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={submit} className="space-y-4">
          <div className={`grid gap-3 ${periodicidad === 'anual' ? 'grid-cols-1' : 'grid-cols-2'}`}>
            <div>
              <Label>Periodicidad</Label>
              <select value={periodicidad} onChange={(e) => handlePeriodicidadChange(e.target.value as Periodicidad)} className="w-full h-9 px-3 rounded-md border bg-background text-sm mt-1">
                {PERIODICIDADES.map(p => <option key={p.value} value={p.value}>{p.label}</option>)}
              </select>
            </div>
            {periodicidad !== 'anual' && (
              <div>
                <Label>Periodo</Label>
                <select value={mes} onChange={(e) => setMes(Number(e.target.value))} className="w-full h-9 px-3 rounded-md border bg-background text-sm mt-1">
                  {periodOptions.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
                </select>
              </div>
            )}
          </div>
          <div className="grid grid-cols-3 gap-3">
            <div>
              <Label>Año</Label>
              <select value={año} onChange={(e) => setAño(Number(e.target.value))} className="w-full h-9 px-3 rounded-md border bg-background text-sm mt-1">
                {yearsOptions.map(y => <option key={y} value={y}>{y}</option>)}
              </select>
            </div>
            <div>
              <Label>Tipo</Label>
              <select value={tipo} onChange={(e) => setTipo(e.target.value as 'normal' | 'complementaria')} className="w-full h-9 px-3 rounded-md border bg-background text-sm mt-1">
                <option value="normal">Normal</option>
                <option value="complementaria">Complementaria</option>
              </select>
            </div>
            <div>
              <Label>Monto a pagar</Label>
              <Input
                type="number"
                min="0"
                step="0.01"
                value={montoPago}
                onChange={(e) => setMontoPago(e.target.value)}
                placeholder="0.00"
                className="mt-1"
              />
              <p className="text-xs text-muted-foreground mt-1">Si es $0.00, se marca como pagado automáticamente.</p>
            </div>
          </div>

          <div>
            <Label>Impuestos cubiertos</Label>
            <div className="grid grid-cols-3 gap-2 mt-1">
              {IMPUESTOS.map(i => (
                <label key={i} className={`flex items-center gap-2 px-3 py-2 rounded-md border cursor-pointer text-sm ${impuestos.includes(i) ? 'bg-primary/10 border-primary' : 'hover:bg-muted'}`}>
                  <input type="checkbox" checked={impuestos.includes(i)} onChange={() => toggleImpuesto(i)} className="accent-primary" />
                  {i}
                </label>
              ))}
            </div>
            <p className="text-xs text-muted-foreground mt-1">Selecciona todos los impuestos que incluye esta declaración — definen qué recordatorios se desactivan.</p>
          </div>

          <div>
            <Label>PDF de la declaración</Label>
            <Input type="file" accept="application/pdf" onChange={(e) => setFile(e.target.files?.[0] || null)} className="mt-1" />
          </div>

          <div>
            <Label>PDF de la liga de pago (opcional)</Label>
            <Input type="file" accept="application/pdf" onChange={(e) => setLigaFile(e.target.files?.[0] || null)} className="mt-1" />
            <p className="text-xs text-muted-foreground mt-1">Documento con la línea de captura/referencia para pagar la declaración.</p>
          </div>

          <div>
            <Label>Notas (opcional)</Label>
            <textarea value={notas} onChange={(e) => setNotas(e.target.value)} rows={2} maxLength={2000} className="w-full px-3 py-2 rounded-md border bg-background text-sm mt-1" />
          </div>

          {err && <div className="p-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">{err}</div>}

          <DialogFooter>
            <Button type="button" variant="outline" onClick={onClose}>Cancelar</Button>
            <Button type="submit" disabled={create.isPending}>
              {create.isPending ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Subiendo...</> : <><Upload className="h-4 w-4 mr-1.5" /> Subir</>}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

// ============================================================================
// Comprobante de Pago Dialog
// ============================================================================
function ComprobantePagoDialog({ declaracion, onClose }: { declaracion: Declaracion; onClose: () => void }) {
  const upload = useUploadComprobantePago();
  const [file, setFile] = useState<File | null>(null);
  const [err, setErr] = useState<string | null>(null);

  const submit = async (e: React.FormEvent) => {
    e.preventDefault();
    setErr(null);
    if (!file) return setErr('Selecciona el PDF del comprobante de pago');
    try {
      const pdfBase64 = await fileToBase64(file);
      await upload.mutateAsync({ id: declaracion.id, pdfBase64, pdfFilename: file.name });
      onClose();
    } catch (e: any) {
      setErr(e?.response?.data?.message || e?.message || 'Error al subir');
    }
  };

  return (
    <Dialog open onOpenChange={(o) => { if (!o) onClose(); }}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Subir comprobante de pago</DialogTitle>
          <DialogDescription>
            {MESES[declaracion.mes - 1]} {declaracion.año} — {declaracion.tipo === 'normal' ? 'Normal' : 'Complementaria'}. Al subirlo se marcan como pagados los recordatorios de pago correspondientes.
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={submit} className="space-y-4">
          <div>
            <Label>PDF del comprobante</Label>
            <Input type="file" accept="application/pdf" onChange={(e) => setFile(e.target.files?.[0] || null)} className="mt-1" />
          </div>
          {err && <div className="p-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">{err}</div>}
          <DialogFooter>
            <Button type="button" variant="outline" onClick={onClose}>Cancelar</Button>
            <Button type="submit" disabled={upload.isPending}>
              {upload.isPending ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Subiendo...</> : <><Upload className="h-4 w-4 mr-1.5" /> Subir</>}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

// ============================================================================
// Extras — PDFs libres (acuses, contratos, poderes, estados de cuenta, etc.)
// ============================================================================

const ROLES_UPLOAD_EXTRA = ['owner', 'cfo', 'contador', 'auxiliar'];

function ExtrasTab() {
  const user = useAuthStore((s) => s.user);
  const canUpload = !!user?.role && ROLES_UPLOAD_EXTRA.includes(user.role);
  const { selectedContribuyenteId } = useContribuyenteStore();
  const qc = useQueryClient();
  const [uploadOpen, setUploadOpen] = useState(false);
  const [categoriaFiltro, setCategoriaFiltro] = useState<string>('');

  const extrasQ = useQuery({
    queryKey: ['documentos-extras', selectedContribuyenteId, categoriaFiltro],
    queryFn: () => docsApi.listarExtras(selectedContribuyenteId, categoriaFiltro || null),
  });

  const categoriasQ = useQuery({
    queryKey: ['documentos-extras-categorias', selectedContribuyenteId],
    queryFn: () => docsApi.listarCategoriasExtras(selectedContribuyenteId),
  });

  const deleteMut = useMutation({
    mutationFn: (id: number) => docsApi.eliminarExtra(id),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['documentos-extras'] });
      qc.invalidateQueries({ queryKey: ['documentos-extras-categorias'] });
    },
  });

  const handleDelete = (id: number, nombre: string) => {
    if (!confirm(`¿Eliminar "${nombre}"? Esta accion no se puede deshacer.`)) return;
    deleteMut.mutate(id);
  };

  const handleDownload = async (id: number, filename: string) => {
    try {
      const blob = await docsApi.descargarExtraPdf(id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = filename;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch {
      alert('Error al descargar el documento');
    }
  };

  const extras = extrasQ.data || [];
  const categorias = categoriasQ.data || [];

  return (
    <Card>
      <CardContent className="pt-6">
        <div className="flex items-center justify-between gap-2 mb-4 flex-wrap">
          <div className="flex items-center gap-3 flex-wrap">
            <h3 className="text-lg font-semibold">Documentos extras</h3>
            {categorias.length > 0 && (
              <div className="flex items-center gap-1.5 text-sm">
                <Tag className="h-4 w-4 text-muted-foreground" />
                <select
                  value={categoriaFiltro}
                  onChange={(e) => setCategoriaFiltro(e.target.value)}
                  className="h-8 rounded-md border border-input bg-background px-2 text-sm"
                >
                  <option value="">Todas las categorias</option>
                  {categorias.map((c) => (
                    <option key={c} value={c}>{c}</option>
                  ))}
                </select>
              </div>
            )}
          </div>
          {canUpload && (
            <Button onClick={() => setUploadOpen(true)} size="sm">
              <Plus className="h-4 w-4 mr-1.5" />
              Subir PDF
            </Button>
          )}
        </div>

        {extrasQ.isLoading ? (
          <div className="text-center py-8 text-muted-foreground">Cargando...</div>
        ) : extras.length === 0 ? (
          <div className="text-center py-8 text-muted-foreground">
            {categoriaFiltro
              ? `No hay documentos en la categoria "${categoriaFiltro}"`
              : 'Aun no hay documentos extras. Sube el primero con el boton de arriba.'}
          </div>
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b text-left text-muted-foreground">
                  <th className="pb-3 font-medium">Nombre</th>
                  <th className="pb-3 font-medium">Categoría</th>
                  <th className="pb-3 font-medium">Descripción</th>
                  <th className="pb-3 font-medium">Subido por</th>
                  <th className="pb-3 font-medium">Fecha</th>
                  <th className="pb-3 font-medium text-right">Acciones</th>
                </tr>
              </thead>
              <tbody>
                {extras.map((e) => (
                  <tr key={e.id} className="border-b hover:bg-muted/50">
                    <td className="py-3 font-medium">{e.nombre}</td>
                    <td className="py-3">
                      {e.categoria ? (
                        <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs bg-muted text-muted-foreground">
                          <Tag className="h-3 w-3" />
                          {e.categoria}
                        </span>
                      ) : (
                        <span className="text-muted-foreground text-xs">—</span>
                      )}
                    </td>
                    <td className="py-3 max-w-[300px] truncate text-muted-foreground" title={e.descripcion || ''}>
                      {e.descripcion || '—'}
                    </td>
                    <td className="py-3 text-xs text-muted-foreground">{e.subidoPor || '—'}</td>
                    <td className="py-3 text-xs text-muted-foreground">
                      {new Date(e.createdAt).toLocaleDateString('es-MX')}
                    </td>
                    <td className="py-3">
                      <div className="flex items-center justify-end gap-1">
                        <Button
                          variant="ghost"
                          size="sm"
                          onClick={() => handleDownload(e.id, e.pdfFilename)}
                          title="Descargar PDF"
                        >
                          <Download className="h-4 w-4" />
                        </Button>
                        {canUpload && (
                          <Button
                            variant="ghost"
                            size="sm"
                            onClick={() => handleDelete(e.id, e.nombre)}
                            disabled={deleteMut.isPending}
                            title="Eliminar"
                            className="hover:text-destructive"
                          >
                            <Trash2 className="h-4 w-4" />
                          </Button>
                        )}
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
            <p className="text-xs text-muted-foreground mt-4">
              {extras.length} documento{extras.length !== 1 ? 's' : ''}
            </p>
          </div>
        )}
      </CardContent>

      {uploadOpen && (
        <UploadExtraDialog
          open={uploadOpen}
          onClose={() => setUploadOpen(false)}
          contribuyenteId={selectedContribuyenteId}
          categoriasExistentes={categorias}
        />
      )}
    </Card>
  );
}

function UploadExtraDialog({
  open, onClose, contribuyenteId, categoriasExistentes,
}: {
  open: boolean;
  onClose: () => void;
  contribuyenteId: string | null;
  categoriasExistentes: string[];
}) {
  const qc = useQueryClient();
  const [nombre, setNombre] = useState('');
  const [descripcion, setDescripcion] = useState('');
  const [categoria, setCategoria] = useState('');
  const [file, setFile] = useState<File | null>(null);
  const [err, setErr] = useState<string | null>(null);

  const upload = useMutation({
    mutationFn: async () => {
      if (!file) throw new Error('Selecciona un archivo PDF');
      if (!nombre.trim()) throw new Error('El nombre es requerido');
      const pdfBase64 = await fileToBase64(file);
      return docsApi.crearExtra(
        {
          nombre: nombre.trim(),
          descripcion: descripcion.trim() || undefined,
          categoria: categoria.trim() || undefined,
          pdfBase64,
          pdfFilename: file.name,
        },
        contribuyenteId,
      );
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['documentos-extras'] });
      qc.invalidateQueries({ queryKey: ['documentos-extras-categorias'] });
      onClose();
    },
    onError: (e: any) => {
      setErr(e?.response?.data?.message || e?.message || 'Error al subir');
    },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    setErr(null);
    upload.mutate();
  };

  return (
    <Dialog open={open} onOpenChange={(o) => !o && onClose()}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Subir documento extra</DialogTitle>
          <DialogDescription>
            PDFs libres como acuses del SAT, contratos, poderes notariales, estados de cuenta, etc.
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={handleSubmit} className="space-y-4 pt-2">
          <div>
            <Label>Nombre *</Label>
            <Input
              value={nombre}
              onChange={(e) => setNombre(e.target.value)}
              placeholder="Ej. Acuse declaracion anual 2024"
              className="mt-1"
              maxLength={255}
            />
          </div>
          <div>
            <Label>Categoría (opcional)</Label>
            <Input
              value={categoria}
              onChange={(e) => setCategoria(e.target.value)}
              placeholder="Ej. Acuses SAT, Contratos, Poderes..."
              className="mt-1"
              list="categorias-extras-list"
              maxLength={100}
            />
            {categoriasExistentes.length > 0 && (
              <datalist id="categorias-extras-list">
                {categoriasExistentes.map((c) => <option key={c} value={c} />)}
              </datalist>
            )}
          </div>
          <div>
            <Label>Descripción (opcional)</Label>
            <textarea
              value={descripcion}
              onChange={(e) => setDescripcion(e.target.value)}
              placeholder="Notas internas sobre el documento"
              rows={3}
              maxLength={2000}
              className="mt-1 flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
            />
          </div>
          <div>
            <Label>PDF *</Label>
            <Input
              type="file"
              accept="application/pdf"
              onChange={(e) => setFile(e.target.files?.[0] || null)}
              className="mt-1"
            />
          </div>
          {err && (
            <div className="p-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 text-sm">
              {err}
            </div>
          )}
          <DialogFooter>
            <Button type="button" variant="outline" onClick={onClose}>Cancelar</Button>
            <Button type="submit" disabled={upload.isPending}>
              {upload.isPending ? (
                <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Subiendo...</>
              ) : (
                <><Upload className="h-4 w-4 mr-1.5" /> Subir</>
              )}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
