// ─── Caja Chica · Detalle de movimiento ────────────────────────────────────
// makeCajaChicaDetail/makeBlankCajaChica + CajaChicaDetailScreen: documento
// editable in-place sobre el motor DocumentShell/DocCard (doc-kit). Extraído de
// screens-others.jsx (P9, split del cajón de 5 módulos). Expone a window:
// CajaChicaDetailScreen. Consume DocumentShell/DocCard/useDocEdit/buildDocActions/
// ConfirmDeleteModal/FileUploadCard (ui/doc-kit-*.jsx), MicosMetaCell
// (ui/doc-kit-meta.jsx), getCajaChicaWithSaldo/resolveResponsableName (lista.jsx),
// expedienteLabelFromId/useExpedienteSeed/resolveExpedienteIdForSave/
// expedienteMetaField (screens/compras/combobox.jsx), MicosCurrentUser
// (dominio/sesion.js).
//
// P9 — write-path real: "Responsable" era un campo de texto LIBRE (cualquier
// nombre tipeado) — la columna real es `responsable_id` (uuid FK a usuarios, P2),
// así que ese texto NUNCA persistía (whitelist lo descartaba en silencio; el
// movimiento se guardaba sin responsable). Fix: select de window.USUARIOS
// (value=id real), default al usuario logueado en el alta — igual que
// "Expediente", que pasa por la misma resolución uuid↔publicId que Compras/
// Logística (ver combobox.jsx).
//
// Fix de raíz (review rechazada, mismo día): esa resolución de Expediente era un
// `find` sobre window.EXPEDIENTES (~500 de ~2100 reales hidratados, BIG_LIMIT) —
// un expediente_id fuera de esa ventana (a) al tipear su publicId de alta
// guardaba null con toast de éxito, y (b, DESTRUCTIVO) al editar sin tocar el
// campo, el draft se sembraba con '' y guardar pisaba en silencio un FK válido
// con null. useExpedienteSeed/resolveExpedienteIdForSave/expedienteMetaField
// (screens/compras/combobox.jsx) resuelven contra el backend antes de sembrar/
// guardar — Responsable no tiene este agujero (responsableId viaja siempre como
// id real, nunca como texto a resolver).
function makeCajaChicaDetail(m) {
  // Sin comprobantes de ejemplo: la tarjeta de adjuntos arranca vacía.
  const archivos = [];
  return { archivos };
}

function makeBlankCajaChica() {
  const cur = (window.MicosCurrentUser && window.MicosCurrentUser()) || null;
  const now = new Date();
  return {
    id: 'cc-' + Date.now(),
    publicId: window.MicosNextSeqId(window.CAJA_CHICA || [], 'publicId', 'CC-', 8),
    tipo: 'EGRESO',
    monto: 0,
    concepto: '',
    empresa: null,
    fecha: (window.MicosTodayISO()),
    hora: String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0'),
    responsableId: (cur && cur.id) || null,
    expedienteId: null,
  };
}

function CajaChicaDetailScreen({ movimientoId, isCreate = false, startEditing = false, onBack, onSaved, onDeleted }) {
  const blank = React.useMemo(() => (isCreate ? makeBlankCajaChica() : null), [isCreate]);
  const { rows } = getCajaChicaWithSaldo();
  const m = isCreate ? blank : (rows.find((x) => x.id === movimientoId) || rows[0]);
  const detail = React.useMemo(() => makeCajaChicaDetail(m), [m.id]);

  const [toast, setToast] = React.useState(null);
  const [confirmDel, setConfirmDel] = React.useState(false);
  const [expedienteError, setExpedienteError] = React.useState(null);

  const { editing, draft, setDraft, enterEdit, discardEdit, saveEdit, patch } = window.useDocEdit(
    () => ({
      tipo: m.tipo || 'EGRESO',
      monto: m.monto || 0,
      concepto: m.concepto || '',
      empresa: m.empresa || '',
      fecha: m.fecha,
      hora: m.hora || '',
      responsableId: m.responsableId || null,
      // Uuid real → publicId visible (ver header). isCreate ya arranca en '' (sin expediente).
      expedienteId: expedienteLabelFromId(m.expedienteId, ''),
    }),
    {
      startEditing: isCreate || startEditing,
      onCancel: () => { if (isCreate || startEditing) onBack && onBack(); },
      onSave: async (d) => {
        // Resolver el texto del combobox (publicId tipeado/elegido) al uuid real —
        // honesto contra la ventana hidratada + backend (fix de raíz, ver header):
        // nunca null en silencio cuando el original tenía un expediente real, y un
        // publicId que no existe aborta el guardado con error inline en el campo.
        const expResolved = await resolveExpedienteIdForSave(d.expedienteId, expSeed.seedLabel, m.expedienteId);
        if (expResolved.notFoundText) {
          setExpedienteError(`No existe el expediente ${expResolved.notFoundText}`);
          return false;
        }
        const obj = {
          ...m,
          tipo: d.tipo,
          monto: Number(d.monto) || 0,
          concepto: (d.concepto || '').trim(),
          empresa: (d.empresa || '').trim() || null,
          fecha: d.fecha,
          hora: d.hora || '',
          responsableId: d.responsableId || null,
          expedienteId: expResolved.id,
        };
        delete obj.saldo; // derivado por getCajaChicaWithSaldo, no se persiste
        if (isCreate) {
          window.MicosStore.create('cajaChica', { ...obj, __nuevo: true });
          onSaved && onSaved(obj.id);
        } else {
          window.MicosStore.update('cajaChica', m.id, obj);
          setToast(`Movimiento ${obj.publicId} guardado`);
          setTimeout(() => setToast(null), 3600);
        }
      },
    }
  );
  const expSeed = useExpedienteSeed(m.expedienteId, editing, patch);
  React.useEffect(() => { if (!editing) setExpedienteError(null); }, [editing]);

  const isIngreso = (editing && draft ? draft.tipo : m.tipo) === 'INGRESO';
  const montoVal = editing && draft ? (Number(draft.monto) || 0) : m.monto;
  const conceptoVal = editing && draft ? draft.concepto : m.concepto;
  const empresaVal = editing && draft ? draft.empresa : m.empresa;
  const montoColor = isIngreso ? 'var(--success)' : 'var(--danger)';
  const montoPrefix = isIngreso ? '+ ' : '− ';
  const responsableNombre = resolveResponsableName(m);
  const expedienteShown = expedienteLabelFromId(m.expedienteId, '');

  const actions = window.buildDocActions({
    editing, enterEdit, discardEdit, saveEdit,
    onDelete: (!isCreate && editing) ? () => setConfirmDel(true) : undefined,
  });

  // P17b (recorrido §3): opción null explícita — responsable_id es nullable (Caja
  // Chica no exige responsable) y los 3 usuarios demo ya no aparecen acá (activo=false
  // tras deshabilitarlos, ver migración 20260703010000_p17b_cuentas_demo_fuera.sql).
  const usuarioOptions = [
    { value: '', label: 'Sin responsable' },
    ...(window.USUARIOS || [])
      .filter((u) => u.activo !== false)
      .map((u) => ({ value: u.id, label: `${u.nombre} ${u.apellido}`.trim() })),
  ];

  const metaFields = [
    { label: 'Concepto', editable: editing, input: 'text',
      value: editing ? draft.concepto : m.concepto, onChange: (v) => patch('concepto', v), placeholder: 'Ej: Pasajes taxi visita Mater Dei' },
    { label: 'Empresa / Proveedor', editable: editing, input: 'text',
      value: editing ? draft.empresa : (m.empresa || '—'), muted: !editing && !m.empresa,
      onChange: (v) => patch('empresa', v), placeholder: 'Opcional — a quién se le pagó' },
    { label: 'Tipo', editable: editing, input: 'select',
      options: [{ value: 'EGRESO', label: 'Egreso (gasto)' }, { value: 'INGRESO', label: 'Ingreso (reposición)' }],
      value: editing ? draft.tipo : (isIngreso ? 'Ingreso' : 'Egreso'), onChange: (v) => patch('tipo', v) },
    { label: 'Fecha', editable: editing, input: 'date', mono: true,
      value: editing ? draft.fecha : formatDate(m.fecha), onChange: (v) => patch('fecha', v) },
    { label: 'Hora', editable: editing, input: 'time', mono: true,
      value: editing ? draft.hora : (m.hora || '—'), onChange: (v) => patch('hora', v) },
    { label: 'Monto', editable: editing, input: 'number', mono: true,
      value: editing ? draft.monto : formatMoney(m.monto), onChange: (v) => patch('monto', v) },
    { label: 'Responsable', editable: editing, input: 'select',
      options: usuarioOptions,
      value: editing ? draft.responsableId : (responsableNombre || 'Sin responsable'),
      muted: !editing && !responsableNombre,
      onChange: (v) => patch('responsableId', v) },
    { label: 'Saldo resultante', value: isCreate ? '—' : formatMoney(m.saldo), mono: !isCreate, muted: isCreate },
    expedienteMetaField({
      editing, expSeed, patch,
      draftValue: draft && draft.expedienteId,
      shownValue: expedienteShown,
      placeholder: 'EXP-… (opcional)',
      mutedWhenEmpty: true,
      error: expedienteError,
      onClearError: () => setExpedienteError(null),
    }),
  ];

  return (
    <DocumentShell
      onBack={onBack}
      backLabel="Volver a Caja Chica"
      eyebrow={`Caja Chica · ${isIngreso ? 'Ingreso' : 'Egreso'}`}
      bigId={m.publicId}
      expedienteId={(editing && draft ? draft.expedienteId : expedienteShown) || '—'}
      fechaEmision={editing && draft ? draft.fecha : m.fecha}
      editing={editing}
      isCreate={isCreate}
      toast={toast}
      actions={actions}
    >
      {/* 1 · Comprobante / documento adjunto */}
      <FileUploadCard
        eyebrow="Documento del movimiento"
        title={isIngreso ? 'Comprobante de reposición' : 'Ticket o factura del gasto'}
        description={isIngreso
          ? 'Subí el comprobante de la transferencia o depósito que repone la caja chica.'
          : 'Adjuntá el ticket, factura o recibo del establecimiento donde se realizó el gasto.'}
        files={detail.archivos}
        editing={editing}
        extractable
        realUpload
      />

      {/* 2 · Datos del movimiento */}
      <DocCard className="p-7 sm:p-8" editing={editing}>
        {/* Header del movimiento */}
        <div className="flex items-start justify-between gap-4 flex-wrap mb-7">
          <div className="min-w-0">
            <p className="text-[11px] font-bold uppercase tracking-[0.2em] mb-2" style={{ color: 'var(--accent)' }}>
              {isIngreso ? 'Ingreso de fondos' : 'Egreso de fondos'}
            </p>
            <p className="text-[22px] font-extrabold tracking-tight leading-[1.15]"
              style={{ color: conceptoVal ? 'var(--foreground)' : 'color-mix(in oklab, var(--muted-foreground) 70%, transparent)' }}>
              {conceptoVal || 'Sin concepto'}
            </p>
            {empresaVal && (
              <p className="text-[13px] mt-1.5" style={{ color: 'var(--muted-foreground)' }}>
                Pagado a <span className="font-bold" style={{ color: 'var(--foreground)' }}>{empresaVal}</span>
              </p>
            )}
          </div>
          <div className="text-right flex-shrink-0">
            <p className="text-[10.5px] font-bold uppercase tracking-[0.18em] mb-1" style={{ color: 'var(--muted-foreground)' }}>
              Monto
            </p>
            <p className="font-mono text-[28px] font-extrabold tabular-nums leading-none" style={{ color: montoColor }}>
              {montoPrefix}{formatMoney(montoVal)}
            </p>
          </div>
        </div>

        {/* Divider */}
        <div style={{ borderTop: '1px solid color-mix(in oklab, var(--border) 55%, transparent)', marginBottom: '1.75rem' }} />

        {/* Datos del movimiento */}
        <p className="text-[11px] font-bold uppercase tracking-[0.2em] mb-6" style={{ color: 'var(--accent)' }}>
          Datos del movimiento
        </p>
        <div className="grid grid-cols-2 sm:grid-cols-3 gap-x-8 gap-y-6">
          {metaFields.map((it, i) => <MicosMetaCell key={i} it={it} />)}
        </div>
      </DocCard>

      {confirmDel && window.ConfirmDeleteModal && (
        <window.ConfirmDeleteModal
          title="¿Eliminar movimiento?"
          itemName={m.publicId}
          description="Se moverá al archivo. Esta acción se puede revertir desde el visor de datos."
          onCancel={() => setConfirmDel(false)}
          onConfirm={() => {
            window.MicosStore.remove('cajaChica', m.id);
            setConfirmDel(false);
            onDeleted && onDeleted();
          }}
        />
      )}
    </DocumentShell>
  );
}

Object.assign(window, { CajaChicaDetailScreen });
