// ─── Dashboard · Directorio (Entidades/Médicos/Particulares) ────────────
// 3 de las 12 secciones del Panel general. Extraídas de screens-dashboard.jsx
// (P10, split en screens/dashboard/). Expone a window: EntidadesSection,
// MedicosSection, ParticularesSection. Consume window.ENTIDADES/MEDICOS/
// PARTICULARES/EXPEDIENTES (core/colecciones.js), useEntityStats (ui/
// entity-list.jsx), DashSection/DashTable/srvOr/TextBold/NumBold
// (compartido.jsx), IdDateCell/KpiCard/TablePill/Avatar (ui/primitives.jsx),
// formatMoney/formatMoneyShort/formatCuit/MicosTodayISO (dominio/formato.js).
//
// FIX (mapa-comprension.md §inv-dash, bug severidad alta — "4 KPI 100%
// hardcodeadas, sin ninguna relación con datos reales"):
//   - MedicosSection: 'Activos (30d)' (value:'6') y 'Derivaciones mes'
//     (value:'47') NO tienen ningún campo real que las respalde — MEDICOS no
//     trackea "última actividad" (solo `estado` ACTIVO/INACTIVO, sin ventana
//     de tiempo) ni "derivaciones de ESTE mes" (`derivaciones` es un
//     acumulado histórico, no mensual, y no hay vista server-side que lo
//     desglose por mes). Se muestran como 'N/D' honesto (doctrina P5/D4) en
//     vez de inventar una fórmula nueva sobre datos que no la sostienen.
//   - ParticularesSection: 'Nuevos este mes' (value:'5') SÍ tiene datos reales
//     que la sostienen (`fechaCreacion`) — se deriva de verdad en vez de
//     mostrarse N/D, mismo criterio que ya usa la lista.
//
// FIX P13 (ítem 14, Review P10 MEDIA-2 — corrige lo de arriba): 'Sin actividad
// >90d' (value:'2') NO quedó resuelta por este mismo fix como decía este
// header — se derivó client-side sobre `window.PARTICULARES` (capado a la
// ventana hidratada, BIG_LIMIT), así que el "1000" mostrado era
// `PARTICULARES.length`, no el universo real (1697) ni una señal útil
// (`ultima_actividad` está NULL en el 100% de las filas reales, gap de la
// migración — verificado psql). Ahora es 'N/D' honesto, mismo criterio que
// MedicosSection (campo sin datos reales que lo sostengan hoy). Ver el
// comentario en ParticularesSection para el detalle completo.
// Además mueren `delta`/`highlighted` (props muertas de KpiCard) en las 3
// secciones.

// ─── Sección · ENTIDADES ──────────────────────────
function EntidadesSection({ onNav }) {
  const totalSaldo = ENTIDADES.reduce((s, e) => s + e.saldoCobrar, 0);
  // Facturado = total de expedientes ya facturados o cobrados (respaldado por datos).
  // Nota: sigue sobre window.EXPEDIENTES (capado a BIG_LIMIT) — no hay vista server-side
  // que agregue "monto facturado" por estado de expediente; fuera del alcance de A4/A6/A7
  // (esos cubren conteos/saldos por entidad/médico/particular, no este cruce puntual).
  const facturadoMes = EXPEDIENTES
    .filter((e) => e.status === 'FACTURA' || e.status === 'RECIBO')
    .reduce((s, e) => s + (e.total || 0), 0);
  // A6/A7 (BUGS-caza-01-07-2026.md #6/#7): "Saldo a cobrar"/"Expedientes" acá sumaban
  // e.saldoCobrar/e.expedientesActivos — campos por-fila que ya vienen del fix A4 (server-
  // side, universo real). v_entidades_stats da el MISMO agregado directo del server (más
  // robusto: no depende de que el recompute local haya corrido), mismo patrón que ya usa
  // la lista de Entidades (screens/directorio/entidades.jsx).
  const srvStats = window.useEntityStats ? window.useEntityStats('entidades') : null;
  const kActivas = srvOr(srvStats, 'activas', ENTIDADES.length);
  const kSaldo = srvOr(srvStats, 'sumSaldoCobrar', totalSaldo);
  const kExp = srvOr(srvStats, 'sumExpedientesActivos', ENTIDADES.reduce((s, e) => s + e.expedientesActivos, 0));

  return (
    <DashSection
      eyebrow="Directorio · Entidades"
      title="Entidades"
      route="entidades"
      onNav={onNav}
      kpis={[
        { label: 'Activas',         value: String(kActivas),        icon: IconBuilding },
        { label: 'Saldo a cobrar',  value: formatMoneyShort(kSaldo), icon: IconWallet },
        { label: 'Facturado',       value: formatMoneyShort(facturadoMes), icon: IconTrendingUp },
        { label: 'Expedientes',     value: String(kExp), icon: IconFileText },
      ]}
      animDelay={480}
    >
      <DashTable
        caption="Últimas 7 entidades"
        onRowClick={() => onNav('entidades')}
        rows={ENTIDADES}
        columns={[
          { key: 'id', label: 'ID', width: '160px',
            render: (e) => <IdDateCell id={e.publicId} date={e.fechaCreacion} /> },
          { key: 'razonSocial', label: 'Razón social', width: '1.6fr',
            render: (e) => (
              <div className="min-w-0">
                <TextBold>{e.razonSocial}</TextBold>
                <p className="text-[11.5px] truncate font-mono tabular-nums" style={{ color: 'var(--muted-foreground)' }}>CUIT {formatCuit(e.cuit)}</p>
              </div>
            ) },
          { key: 'condicionVenta', label: 'Cond. venta', width: '130px',
            render: (e) => <TablePill label={e.condicionVenta} tone="info" /> },
          { key: 'activos', label: 'Activos', width: '90px', align: 'right',
            render: (e) => <NumBold>{e.expedientesActivos}</NumBold> },
          { key: 'saldo', label: 'Saldo a cobrar', width: '160px', align: 'right',
            render: (e) => <NumBold>{formatMoney(e.saldoCobrar)}</NumBold> },
        ]}
      />
    </DashSection>
  );
}

// ─── Sección · MÉDICOS ────────────────────────────
function MedicosSection({ onNav }) {
  // A7 (BUGS-caza-01-07-2026.md #7): MEDICOS no está capado a BIG_LIMIT (colección chica),
  // así que "Registrados"/"Especialidades" ya eran correctos; se conecta igual a
  // v_medicos_stats por consistencia con el resto del Panel (mismo patrón que la lista,
  // screens/directorio/medicos.jsx).
  const srvStats = window.useEntityStats ? window.useEntityStats('medicos') : null;
  const kEspecialidades = srvOr(srvStats, 'especialidades', new Set(MEDICOS.map(m => m.especialidad)).size);

  return (
    <DashSection
      eyebrow="Directorio · Médicos"
      title="Médicos"
      route="medicos"
      onNav={onNav}
      kpis={[
        { label: 'Registrados',     value: String(MEDICOS.length), icon: IconStethoscope },
        { label: 'Especialidades',  value: String(kEspecialidades), icon: IconBriefcase },
        // FIX (ver header): sin campo real de "actividad en 30 días" ni de
        // "derivaciones de este mes" — N/D honesto en vez de las literales
        // '6'/'47' que no respondían a ningún dato.
        { label: 'Activos (30d)',   value: 'N/D', icon: IconTrendingUp },
        { label: 'Derivaciones mes', value: 'N/D', icon: IconArrowUpRight },
      ]}
      animDelay={540}
    >
      <DashTable
        caption="Últimos 7 médicos"
        onRowClick={() => onNav('medicos')}
        rows={MEDICOS}
        columns={[
          { key: 'id', label: 'ID', width: '160px',
            render: (m) => <IdDateCell id={m.publicId} date={m.fechaCreacion} /> },
          { key: 'nombre', label: 'Médico', width: '1.6fr',
            render: (m) => (
              <div className="flex items-center gap-3 min-w-0">
                <Avatar name={`${m.nombre} ${m.apellido}`} size={32} />
                <div className="min-w-0">
                  <TextBold>{m.nombre} {m.apellido}</TextBold>
                  <p className="text-[11.5px] truncate font-mono tabular-nums" style={{ color: 'var(--muted-foreground)' }}>{m.matricula}</p>
                </div>
              </div>
            ) },
          { key: 'especialidad', label: 'Especialidad', width: '180px',
            render: (m) => <TablePill label={m.especialidad} tone="accent" /> },
          { key: 'expedientes', label: 'Exp.', width: '90px', align: 'right',
            render: (m) => <NumBold>{m.expedientes}</NumBold> },
          { key: 'derivaciones', label: 'Derivaciones', width: '120px', align: 'right',
            render: (m) => <NumBold>{m.derivaciones}</NumBold> },
        ]}
      />
    </DashSection>
  );
}

// ─── Sección · PARTICULARES ───────────────────────
function ParticularesSection({ onNav }) {
  const totalExp = PARTICULARES.reduce((s, p) => s + p.expedientes, 0);
  // A6/A7 (BUGS-caza-01-07-2026.md #6/#7): "Expedientes activos" sumaba p.expedientes —
  // campo por-fila que ya viene del fix A4 (server-side, universo real). v_particulares_
  // stats da el MISMO agregado directo del server (más robusto, mismo patrón que la lista).
  const srvStats = window.useEntityStats ? window.useEntityStats('particulares') : null;
  const kRegistrados = srvOr(srvStats, 'total', PARTICULARES.length);
  const kExp = srvOr(srvStats, 'sumExpedientes', totalExp);

  // FIX (ver header del archivo): 'Nuevos este mes' SÍ es derivable de datos
  // reales ya hidratados (mismo criterio/campo que screens/directorio/
  // particulares.jsx) — se calcula de verdad en vez del 'N/D' que ameritaría
  // MedicosSection (sin campo real que la respalde).
  const hoy = window.MicosTodayISO ? window.MicosTodayISO() : new Date().toISOString().slice(0, 10);
  const mesActual = hoy.slice(0, 7); // 'YYYY-MM'
  const nuevosEsteMes = PARTICULARES.filter((p) => (p.fechaCreacion || '').slice(0, 7) === mesActual).length;
  // FIX P13 (ítem 14, Review P10 MEDIA-2): 'Sin actividad >90d' ANTES se calculaba
  // client-side sobre window.PARTICULARES (capado a la ventana hidratada) — el valor
  // mostrado (1000) era exactamente PARTICULARES.length, no el universo real (1697).
  // Además `ultima_actividad` está NULL en el 100% de las filas reales (gap de la
  // migración, verificado psql): aunque se corrigiera la ventana, el número sería
  // literal el total (100% "sin actividad"), un dato que no aporta señal real — mismo
  // caso que MedicosSection (campo sin datos que lo sostengan), no el de "Nuevos este
  // mes" (que sí tiene datos reales). Consistente con esa sección: 'N/D' honesto en vez
  // de un número que parece un bug (idéntico al total de registrados).

  return (
    <DashSection
      eyebrow="Directorio · Particulares"
      title="Particulares"
      route="particulares"
      onNav={onNav}
      kpis={[
        { label: 'Registrados',         value: String(kRegistrados), icon: IconUsers },
        { label: 'Expedientes activos', value: String(kExp), icon: IconFileText },
        { label: 'Nuevos este mes',     value: String(nuevosEsteMes), icon: IconTrendingUp },
        { label: 'Sin actividad >90d',  value: 'N/D', icon: IconClock },
      ]}
      animDelay={600}
    >
      <DashTable
        caption="Últimos 7 particulares"
        onRowClick={() => onNav('particulares')}
        rows={PARTICULARES}
        columns={[
          { key: 'id', label: 'ID', width: '160px',
            render: (p) => <IdDateCell id={p.publicId} date={p.fechaCreacion} /> },
          { key: 'nombre', label: 'Paciente', width: '1.4fr',
            render: (p) => (
              <div className="flex items-center gap-3 min-w-0">
                <Avatar name={`${p.nombre} ${p.apellido}`} size={32} />
                <div className="min-w-0">
                  <TextBold>{p.nombre} {p.apellido}</TextBold>
                  <p className="text-[11.5px] truncate font-mono tabular-nums" style={{ color: 'var(--muted-foreground)' }}>DNI {p.dni}</p>
                </div>
              </div>
            ) },
          { key: 'telefono', label: 'Teléfono', width: '160px',
            render: (p) => <span className="text-[12.5px]" style={{ color: 'var(--muted-foreground)' }}>{p.telefono}</span> },
          { key: 'vendedor', label: 'Vendedor', width: '130px',
            render: (p) => <span className="text-[12.5px] font-semibold" style={{ color: 'var(--foreground)' }}>{p.vendedor}</span> },
          { key: 'expedientes', label: 'Expedientes', width: '110px', align: 'right',
            render: (p) => <NumBold>{p.expedientes}</NumBold> },
        ]}
      />
    </DashSection>
  );
}

Object.assign(window, { EntidadesSection, MedicosSection, ParticularesSection });
