// ─── Doc-kit: shell + cards (1/4) ───────────────────────────────────
// El armazón visual de "documento editable": DocumentShell (header+back+
// acciones+body grid), DocCard (contenedor reusable), PartyBlock (Emisor/
// Cliente/Comprador/Proveedor), Totals (desglose+banner de total),
// ObservacionesCard, MedicalContextCard ("Datos del expediente" — P17b: ex
// "Datos médicos", ahora las 3 partes paciente/médico/entidad) y los
// builders de campos buildEmisorFields/buildClienteFields. Extraído de
// screens-docs.jsx en P4 — es LA librería de "documento editable" que reusan
// Finanzas, Compras/Aprobaciones, Inventario, Directorio y el motor de listas.
// Expone a window: DocumentShell, DocCard, PartyBlock, Totals,
// ObservacionesCard, MedicalContextCard, buildEmisorFields, buildClienteFields.
// Consume window.formatMoney/formatDate/formatDateLong/formatCuit (dominio/
// formato.js), window.ENTIDADES/PARTICULARES (colecciones hidratadas),
// Icon* (ui/icons.jsx).
// P4: DocumentShell pierde el prop `sidebar` (muerto — 0 callers en todo el
// repo pasaban ese prop; el bloque de sidebar/StatusTimeline/InfoBlock que
// dependía de él también murió, ver ui/dir-kit no — ver los "muertos" del
// paquete: TimelineNode/InfoRow/StatusTimeline/InfoBlock quedaron en
// screens-docs.jsx marcados para borrar, no acá).

// ─── Party block (Emisor / Cliente / Comprador / Proveedor) ──
// Supports two render modes:
//   · `lines`  → simple subtitle list (used by OC, Factura legacy)
//   · `fields` → label/value grid (used by Presupuesto for full company/client data)
// `onEdit` renders an icon button in the top-right (e.g. "change associated client").
function PartyBlock({ eyebrow, name, sub, lines = [], fields = [], onEdit, editLabel = 'Cambiar' }) {
  return (
    <div className="space-y-4 relative">
      <p className="text-[11px] font-bold uppercase tracking-[0.2em]" style={{ color: 'var(--accent)' }}>
        {eyebrow}
      </p>
      {onEdit &&
        <button
          onClick={onEdit}
          title={editLabel}
          className="party-edit-btn absolute right-0 top-0"
          type="button">
          <IconPencil size={13} />
        </button>
      }
      <div className="space-y-1.5">
        <p className="text-[22px] font-extrabold tracking-[-0.01em] leading-tight" style={{ color: 'var(--foreground)' }}>
          {name}
        </p>
        {sub &&
        <p className="text-[11px] font-bold uppercase tracking-[0.12em]" style={{ color: 'var(--muted-foreground)' }}>
            {sub}
          </p>
        }
      </div>

      {/* Lines mode */}
      {lines.length > 0 &&
      <div className="space-y-1.5 pt-2">
          {lines.map((line, i) =>
        <p key={i} className="text-[13px]" style={{ color: 'var(--muted-foreground)' }}>
              {line}
            </p>
        )}
        </div>
      }

      {/* Fields mode */}
      {fields.length > 0 &&
      <dl className="grid grid-cols-1 gap-y-4 pt-4" style={{ borderTop: '1px solid color-mix(in oklab, var(--border) 45%, transparent)' }}>
          {fields.map((f, i) =>
        <div key={i} className="grid grid-cols-[110px_1fr] gap-4 items-baseline">
              <dt className="text-[10.5px] font-bold uppercase tracking-[0.12em]" style={{ color: 'var(--muted-foreground)' }}>
                {f.label}
              </dt>
              <dd className={`text-[13.5px] font-semibold leading-snug ${f.mono ? 'font-mono tabular-nums' : ''}`}
          style={{ color: 'var(--foreground)', wordBreak: 'break-word' }}>
                {f.value || '—'}
              </dd>
            </div>
        )}
        </dl>
      }
    </div>);

}

// ─── Shared Emisor / Cliente field builders ────────
// Same shape used across Presupuesto, OC (Comprador), Remito, Factura, Recibo
// so the data layout stays consistent.
function buildEmisorFields(co) {
  return [
    { label: 'CUIT', value: co.cuit, mono: true },
    // P17a (recorrido §9): IIBB en la misma fuente mono que el CUIT — quedaba
    // sin `mono: true`, único campo numérico/código de este bloque sin ese
    // tratamiento (se ve en el PartyBlock "Emisor" de los 8 documentos que
    // usan este builder: Presupuesto/OC/Remito/Factura/Recibo/Nota/Pago/
    // Factura Recibida).
    { label: 'IIBB', value: co.ingresosBrutos, mono: true },
    { label: 'Inicio Act.', value: formatDate(co.inicioActividades), mono: true },
    { label: 'Domicilio', value: `${co.direccion}, ${co.localidad}` },
    { label: 'Teléfono', value: co.telefono, mono: true },
    { label: 'Email', value: co.email },
  ];
}
function buildClienteFields(exp) {
  if (exp.entidad || exp.entidadId) {
    // Resolver SIEMPRE desde el directorio (ENTIDADES) por id; el snapshot del
    // expediente solo trae el nombre. El snapshot pisa lo editable.
    const dir = (window.ENTIDADES || []).find((x) => x.id === exp.entidadId) || {};
    const e = { ...dir, ...(exp.entidad || {}) };
    const contacto = (e.contactos && e.contactos[0]) || {};
    const domicilio = [e.domicilio, e.localidad].filter(Boolean).join(', ') || null;
    return [
      { label: 'CUIT', value: e.cuit, mono: true },
      { label: 'Cond. IVA', value: e.condicionIva },
      { label: 'Cond. venta', value: e.condicionVenta || e.plazoPago },
      { label: 'Domicilio', value: domicilio },
      { label: 'Teléfono', value: e.telefono || contacto.telefono, mono: true },
      { label: 'Email', value: e.email || contacto.email },
      { label: 'Convenio', value: e.convenio },
    ].filter((f) => f.value);
  }
  // Particular: el snapshot embebido suele traer solo nombre/dni/teléfono; el
  // domicilio/localidad/email viven en el directorio. Resolvemos por id y dejamos
  // que el snapshot pise lo editable. Mismo orden de campos que el Emisor.
  const dir = (window.PARTICULARES || []).find((p) => p.id === exp.particularId) || {};
  const par = { ...dir, ...(exp.particular || {}) };
  const domicilio = par.domicilio
    ? [par.domicilio, par.localidad].filter(Boolean).join(', ')
    : null;
  return [
    { label: 'DNI', value: par.dni, mono: true },
    { label: 'Domicilio', value: domicilio },
    { label: 'Teléfono', value: par.telefono, mono: true },
    { label: 'Email', value: par.email },
  ].filter((f) => f.value);
}

// ─── Totals (bottom of items) ─────────────────────
// Variation B: horizontal strip of subtotals + full-width total banner.
function Totals({ subtotal, bonificaciones, iva, ivaLines, total, hideIva = false, importeLetras }) {
  const ivaTotal = ivaLines && ivaLines.length > 0 ?
  ivaLines.reduce((s, l) => s + l.monto, 0) :
  iva;
  const ivaLabel = ivaLines && ivaLines.length === 1 ?
  ivaLines[0].label :
  'IVA';

  // Build the breakdown cells (filter out empties)
  const cells = [
  { label: 'Subtotal', value: formatMoney(subtotal) },
  bonificaciones != null && bonificaciones > 0 ?
  { label: 'Bonificaciones', value: `− ${formatMoney(bonificaciones)}`, tone: 'neg' } :
  null,
  !hideIva && ivaTotal != null ?
  { label: ivaLabel, value: formatMoney(ivaTotal) } :
  null].
  filter(Boolean);

  return (
    <div className="mt-8 space-y-4">
      {/* Breakdown strip */}
      <div className="rounded-xl"
      style={{
        border: '1px solid color-mix(in oklab, var(--border) 55%, transparent)',
        background: 'color-mix(in oklab, var(--surface) 35%, transparent)'
      }}>
        <div className={`grid divide-x grid-cols-${cells.length}`}
        style={{ '--tw-divide-opacity': 1, borderColor: 'color-mix(in oklab, var(--border) 55%, transparent)' }}>
          {cells.map((c, i) =>
          <div
            key={i}
            className="px-5 py-4 space-y-2"
            style={{
              borderLeft: i > 0 ? '1px solid color-mix(in oklab, var(--border) 45%, transparent)' : 'none'
            }}>
              <p className="text-[10.5px] font-bold uppercase tracking-[0.14em]" style={{ color: 'var(--muted-foreground)' }}>
                {c.label}
              </p>
              <p className="text-[18px] font-extrabold tabular-nums tracking-tight leading-none"
            style={{ color: c.tone === 'neg' ? 'var(--danger)' : 'var(--foreground)' }}>
                {c.value}
              </p>
            </div>
          )}
        </div>
      </div>

      {/* Total banner */}
      <div className="rounded-xl px-6 py-5"
      style={{
        background: 'var(--card)',
        border: '1px solid color-mix(in oklab, var(--border) 55%, transparent)'
      }}>
        <div className="flex flex-wrap items-end justify-between gap-3">
          <div className="space-y-1">
            <p className="text-[11px] font-bold uppercase tracking-[0.2em]" style={{ color: 'var(--foreground)' }}>
              {hideIva ? 'Total (sin IVA)' : 'Total'}
            </p>
            {importeLetras &&
            <p className="text-[11.5px] leading-snug max-w-[44ch]" style={{ color: 'var(--muted-foreground)' }}>
                {importeLetras}
              </p>
            }
          </div>
          <p className="text-[clamp(32px,4.6vw,42px)] font-extrabold tabular-nums tracking-[-0.02em] leading-none" style={{ color: 'var(--accent)' }}>
            {formatMoney(total)}
          </p>
        </div>
      </div>
    </div>);

}

// ─── Doc shell ────────────────────────────────────
function DocumentShell({ onBack, backLabel = 'Volver al expediente', eyebrow, bigId, expedienteId, fechaEmision, primaryAction = 'Editar', actions, editing = false, isCreate = false, toast, children, subtitle, statusLabel, statusPill }) {
  // Rule 7: cuando un valor mostrado se reemplaza, el texto nuevo entra de
  // derecha a izquierda (animate-name-pop). Detectamos el reemplazo con refs
  // para no animar en el primer montaje.
  const _bigSeen = React.useRef(null);
  const _bigChanged = _bigSeen.current !== null && _bigSeen.current !== bigId;
  React.useEffect(() => { _bigSeen.current = bigId; }, [bigId]);
  const _fechaSeen = React.useRef(null);
  const _fechaChanged = _fechaSeen.current !== null && _fechaSeen.current !== fechaEmision;
  React.useEffect(() => { _fechaSeen.current = fechaEmision; }, [fechaEmision]);
  return (
    <div className="space-y-7 pt-2">
      {/* Back */}
      <button onClick={onBack}
      className="flex items-center gap-2 text-[11px] font-bold uppercase tracking-[0.12em] cursor-pointer transition-colors animate-fade-in-up"
      style={{ color: 'var(--muted-foreground)' }}
      onMouseEnter={(e) => e.currentTarget.style.color = 'var(--accent)'}
      onMouseLeave={(e) => e.currentTarget.style.color = 'var(--muted-foreground)'}>

        <IconArrowLeft size={13} />
        {backLabel}
      </button>

      {/* Header */}
      <div className="flex flex-wrap items-start justify-between gap-4 animate-fade-in-up" style={{ animationDelay: '40ms' }}>
        <div className="space-y-3 min-w-0">
          <div className="flex items-center gap-3 flex-wrap">
            <span className="text-[11px] font-bold uppercase tracking-[0.18em]" style={{ color: 'var(--accent)' }}>
              {eyebrow}
            </span>
            {editing ? (
              <span className="pill pill-presupuesto" style={{ padding: '4px 12px', fontSize: '10.5px' }}>
                {isCreate ? 'Nuevo' : 'Editando'}
              </span>
            ) : (statusLabel ? (
              // Pill de estado del documento (view mode). `statusLabel`/`statusPill` los pasan las
              // pantallas de documento desde P7 pero DocumentShell nunca los pintaba (props muertas);
              // acá se cablean. Para Presupuesto/OC/Remito el label refleja el ESTADO PERSISTIDO real
              // (ver cada screen); las demás traen su rótulo propio (Cargada/Emitida/Cobrado, etc.).
              <span className={`pill ${statusPill || 'pill-presupuesto'}`} style={{ padding: '4px 12px', fontSize: '10.5px' }}>
                {statusLabel}
              </span>
            ) : null)}
          </div>
          <h1 key={bigId} className={`font-mono text-[clamp(28px,4.2vw,40px)] leading-[1.05] font-extrabold tracking-[-0.01em] break-all ${_bigChanged ? 'animate-name-pop' : ''}`} style={{ color: 'var(--foreground)' }}>
            {bigId}
          </h1>
          <p className="text-[13.5px] font-medium" style={{ color: 'var(--muted-foreground)' }}>
            {subtitle ? subtitle : <>Expediente <span className="font-mono font-bold" style={{ color: 'var(--accent)' }}>{expedienteId}</span>
            <span className="mx-1.5 opacity-50">·</span>
            Emitido el <span key={fechaEmision} className={`inline-block ${_fechaChanged ? 'animate-name-pop' : ''}`}>{formatDateLong(fechaEmision)}</span></>}
          </p>
        </div>
        <div className="flex items-center gap-2 flex-shrink-0 flex-wrap">
          {actions || (
            <button className="btn btn-primary">
              <IconPencil size={14} />
              <span className="hidden sm:inline">{primaryAction}</span>
            </button>
          )}
        </div>
      </div>

      {/* Body — remount on edit-mode toggle so cards re-animate in */}
      <div
        key={editing ? 'edit' : 'view'}
        className="animate-fade-in-up"
        style={{ animationDelay: '80ms' }}>
        <div className="min-w-0 space-y-7 stagger">{children}</div>
      </div>

      {/* Toast de confirmación (crear / guardar) */}
      {toast && (
        <div
          className="fixed bottom-6 right-6 z-50 flex items-center gap-3 rounded-xl px-4 py-3 animate-fade-in-up"
          style={{
            background: 'var(--card)',
            border: '1px solid color-mix(in oklab, var(--accent) 45%, transparent)',
            boxShadow: '0 18px 50px -14px rgba(8, 20, 24, 0.5)',
            maxWidth: 'min(92vw, 380px)',
          }}>
          <span className="inline-flex items-center justify-center rounded-lg flex-shrink-0"
            style={{ width: 30, height: 30, background: 'color-mix(in oklab, var(--accent) 16%, transparent)', color: 'var(--accent)' }}>
            <IconCheck size={16} />
          </span>
          <p className="text-[12.5px] font-bold truncate" style={{ color: 'var(--foreground)' }}>
            {toast}
          </p>
        </div>
      )}
    </div>);

}

// ─── Card (re-usable container) ───────────────────
function DocCard({ children, className = '', editing = false }) {
  return (
    <div className={`rounded-2xl bg-card p-6 sm:p-8 ${editing ? 'doc-card--editing' : ''} ${className}`} style={{
      border: '1px solid color-mix(in oklab, var(--border) 55%, transparent)',
      boxShadow: 'var(--shadow-card)'
    }}>
      {children}
    </div>);

}

// ─── Shared sub-card: Datos del expediente (P17b — recorrido §7: era "Datos
// médicos del expediente" y solo mostraba paciente+médico; pasa a "Datos del
// expediente" e incluye la ENTIDAD, las 3 partes, mismo criterio que el
// header del alta/detalle — `ent?.razonSocial || 'Particular'`, ver
// detalle.jsx) ──
function MedicalContextCard({ exp }) {
  const par = exp.particular || {};
  const med = exp.medico || {};
  const ent = exp.entidad || null;
  const pacienteName = `${par.nombre || ''} ${par.apellido || ''}`.trim() || 'Sin paciente';
  const medicoName = `${med.titulo ? med.titulo + ' ' : ''}${med.nombre || ''} ${med.apellido || ''}`.trim() || 'Sin médico';
  const medicoSub = [med.especialidad, med.matricula].filter(Boolean).join(' · ');
  const entidadName = (ent && ent.razonSocial) || 'Particular';
  const entidadSub = ent
    ? [ent.cuit ? `CUIT ${formatCuit(ent.cuit)}` : null, ent.convenio].filter(Boolean).join(' · ')
    : 'Pago directo del paciente';
  return (
    <DocCard>
      <p className="text-[11px] font-bold uppercase tracking-[0.2em] mb-5" style={{ color: 'var(--accent)' }}>
        Datos del expediente
      </p>
      <div className="grid grid-cols-1 md:grid-cols-3 gap-7">
        <div className="space-y-1.5">
          <p className="text-[10.5px] font-bold uppercase tracking-[0.14em]" style={{ color: 'var(--muted-foreground)' }}>
            Paciente
          </p>
          <p className="text-[19px] font-extrabold tracking-[-0.01em]" style={{ color: 'var(--foreground)' }}>
            {pacienteName}
          </p>
          <p className="text-[12.5px] pt-1" style={{ color: 'var(--muted-foreground)' }}>
            {par.dni ? `DNI ${par.dni}` : 'Sin DNI cargado'}
          </p>
        </div>
        <div className="space-y-1.5">
          <p className="text-[10.5px] font-bold uppercase tracking-[0.14em]" style={{ color: 'var(--muted-foreground)' }}>
            Médico tratante
          </p>
          <p className="text-[19px] font-extrabold tracking-[-0.01em]" style={{ color: 'var(--foreground)' }}>
            {medicoName}
          </p>
          <p className="text-[12.5px] pt-1" style={{ color: 'var(--muted-foreground)' }}>
            {medicoSub || 'Sin datos del médico'}
          </p>
        </div>
        <div className="space-y-1.5">
          <p className="text-[10.5px] font-bold uppercase tracking-[0.14em]" style={{ color: 'var(--muted-foreground)' }}>
            Entidad / Cobertura
          </p>
          <p className="text-[19px] font-extrabold tracking-[-0.01em]" style={{ color: 'var(--foreground)' }}>
            {entidadName}
          </p>
          <p className="text-[12.5px] pt-1" style={{ color: 'var(--muted-foreground)' }}>
            {entidadSub}
          </p>
        </div>
      </div>
    </DocCard>
  );
}

// ─── Shared sub-card: Observaciones (read + edit) ──
function ObservacionesCard({ editing, value, onChange, placeholder = 'Notas, condiciones particulares o instrucciones…' }) {
  if (!editing && !value) return null;
  return (
    <DocCard editing={editing}>
      <p className="text-[11px] font-bold uppercase tracking-[0.2em] mb-5" style={{ color: 'var(--accent)' }}>
        Observaciones
      </p>
      {editing ? (
        <textarea
          value={value || ''}
          onChange={(e) => onChange(e.target.value)}
          rows={3}
          placeholder={placeholder}
          className="edit-textarea text-[14px] font-bold leading-snug"
        />
      ) : (
        <p className="text-[14px] font-bold leading-snug whitespace-pre-line" style={{ color: 'var(--foreground)' }}>
          {value}
        </p>
      )}
    </DocCard>
  );
}

Object.assign(window, {
  DocumentShell, DocCard, PartyBlock, Totals, ObservacionesCard, MedicalContextCard,
  buildEmisorFields, buildClienteFields,
});
