// ─── Finanzas · Nota de Crédito / Débito (alta / edición / vista) ─────────
// NotaScreen: detalle rico de NC/ND (colección NOTAS_CREDITO/NOTAS_DEBITO),
// calcado del layout de FacturaScreen. Movida de screens-finanzas-detalle.jsx
// (P8) sin cambios de comportamiento — "tomar tal cual" (mapa-comprension.md
// §Reutilización: "buen ejemplo a seguir" por su separación explícita
// columnas-reales-vs-locales del backend). Único cambio: `_ndClienteFields`
// (copia carácter por carácter de `_facClienteFields`) se colapsa en
// `buildClienteFieldsCompacto` (screens/finanzas/compartido.jsx, mapa
// §finanzas duplicación #4). Expone a window: NotaScreen. Consume window.
// resolveDocExp NO — standalone, no depende de expediente. DocumentShell/
// DocCard/PartyBlock/Totals/ObservacionesCard/buildEmisorFields (ui/doc-kit-
// shell.jsx), buildClienteFieldsCompacto (screens/finanzas/compartido.jsx),
// DocMetaStrip (ui/doc-kit-meta.jsx), ItemsTable (ui/doc-kit-items.jsx),
// useDocEdit/buildDocActions/ConfirmDeleteModal (ui/doc-kit-edit.jsx),
// window.PartySelectorModal, MicosNextSeqId (dominio/secuencias.js),
// MicosItemsMath, MicosStore, MicosDocNotaMod/openPrintDoc.

function resolverNota(id) {
  return (window.NOTAS_CREDITO || []).find(n => n.id === id)
      || (window.NOTAS_DEBITO || []).find(n => n.id === id) || null;
}

// Código de comprobante fiscal por clase+tipo (NC-A 03 · NC-B 08 · ND-A 02 · ND-B 07).
const ND_COD = { 'NC-A': '03', 'NC-B': '08', 'ND-A': '02', 'ND-B': '07' };
// P5: _ndNextNum se fusionó en MicosNextSeqId (dominio/secuencias.js).
function makeBlankNota(clase, lado) {
  const cl = clase === 'ND' ? 'ND' : 'NC';
  const ladoN = lado === 'pagos' ? 'pago' : 'cobro';
  const tipo = 'A';
  const hoy = MicosTodayISO();
  const numero = MicosNextSeqId(window[cl === 'ND' ? 'NOTAS_DEBITO' : 'NOTAS_CREDITO'] || [], 'numero', '', 8);
  return {
    id: (cl === 'ND' ? 'nd' : 'nc') + '-' + Date.now(),
    publicId: `${cl}-${tipo}-0001-${numero}`,
    clase: cl, tipo, lado: ladoN,
    titulo: cl === 'ND' ? 'Nota de Débito' : 'Nota de Crédito',
    codComprobante: ND_COD[`${cl}-${tipo}`],
    puntoVenta: '0001', numero,
    fechaEmision: hoy, fechaVencimiento: hoy,
    comprobanteAsociado: '', estado: 'PENDIENTE',
    cae: '', caeVto: '',
    cliente: null, proveedor: '',
    items: [], total: 0,
  };
}

function NotaScreen({ notaId, isCreate = false, clase = 'NC', lado = 'cobros', onBack, onSaved, backLabel }) {
  const blank = React.useMemo(() => (isCreate ? makeBlankNota(clase, lado) : null), [isCreate, clase, lado]);
  const nota = isCreate ? blank : resolverNota(notaId);
  const co = COMPANY_CONFIG;
  const [toast, setToast] = React.useState(null);
  const [confirmDel, setConfirmDel] = React.useState(false);
  const [provPicker, setProvPicker] = React.useState(false);
  const M = MicosItemsMath;

  const original = React.useMemo(() => nota, [nota && nota.id]);

  // "Comprobante asociado" a mostrar/heredar al editar: preferimos el número guardado en sesión
  // (`comprobanteAsociado`, texto libre legacy); si la nota vino del backend solo con la FK real
  // (`comprobanteAsociadoId`, columna `comprobante_asociado_id` → facturas.id), resolvemos el
  // número de esa factura desde la colección FACTURAS ya hidratada.
  const compAsocResuelto = React.useMemo(() => {
    if (!original) return '';
    if (original.comprobanteAsociado) return original.comprobanteAsociado;
    if (!original.comprobanteAsociadoId) return '';
    const f = (window.FACTURAS || []).find((x) => x.id === original.comprobanteAsociadoId);
    return f ? `${f.tipoFactura}-${String(f.puntoVenta || '').padStart(4, '0')}-${f.numero}` : '';
  }, [original && original.id, original && original.comprobanteAsociadoId, original && original.comprobanteAsociado]);

  const { editing, draft, setDraft, enterEdit, discardEdit, saveEdit, patch } = useDocEdit(() => ({
    tipo: original.tipo,
    puntoVenta: original.puntoVenta,
    numero: original.numero,
    fechaEmision: original.fechaEmision,
    fechaVencimiento: original.fechaVencimiento,
    comprobanteAsociado: compAsocResuelto,
    // FK real detrás de "Comprobante asociado" (comprobante_asociado_id → facturas.id). En cobros
    // la puebla el picker de facturas (abajo); en pagos no aplica (la FK apunta a `facturas`).
    comprobanteAsociadoId: original.comprobanteAsociadoId || null,
    estado: original.estado,
    cae: original.cae || '',
    caeVto: original.caeVto || '',
    observaciones: original.observaciones || '',
    cliente: original.cliente || null,
    // FK reales detrás de `cliente` (entidad_id en cobros, proveedor_id en pagos). Vienen
    // camelizadas mecánicamente desde el GET (son columnas reales, no un embed derivado).
    entidadId: original.entidadId || null,
    proveedorId: original.proveedorId || null,
    items: (original.items || []).map(it => M.migrate(it)),
  }), {
    startEditing: isCreate,
    onCancel: () => { if (isCreate) onBack && onBack(); },
    onSave: (d) => {
      // Mismo bug/fix que la factura standalone: si la nota no tiene ítems
      // reales (migrada sin nota_credito_item/nota_debito_item), no
      // recalcular el total en $0 — preservar el total de cabecera persistido.
      const hasItemsSave = (d.items || []).length > 0;
      const total = hasItemsSave
        ? Math.round(M.summary(d.items).total * 100) / 100
        : (Number(original.total) || 0);
      const cod = ND_COD[`${original.clase}-${d.tipo}`] || original.codComprobante;
      // Columnas reales de notas_credito/notas_debito (schema real, docker exec
      // \d notas_credito): clase, tipo, lado, cod_comprobante, comprobante_asociado_id,
      // entidad_id, proveedor_id, total, fecha_emision, fecha_vencimiento, punto_venta,
      // numero, condicion_venta, cae, cae_venc, estado, observaciones (las últimas 2,
      // sumadas por el cimiento de fase 3 — migración 20260705220000_f3_columnas.sql —
      // y cableadas acá, fase 3 finanzas: hallazgo MEDIA "Nota de crédito/débito: Estado +
      // Comp. asociado + Observaciones sin columnas"). La FK real `comprobante_asociado_id`
      // (→ facturas.id) YA SE CABLEA (decisión de producto tomada: selector real sobre la FK,
      // no texto libre) vía el picker de facturas de abajo, que setea `comprobanteAsociadoId`
      // en el draft — se manda en el payload (solo tiene sentido en cobros; en pagos queda null
      // porque la FK apunta a `facturas`). `cliente` (objeto) sigue sin ser columna: se resuelve
      // a entidadId/proveedorId (FK real, ver PartySelectorModal onPick más abajo).
      const payload = {
        tipo: d.tipo, puntoVenta: d.puntoVenta, numero: d.numero, codComprobante: cod,
        fechaEmision: d.fechaEmision, fechaVencimiento: d.fechaVencimiento,
        cae: d.cae, caeVto: d.caeVto, estado: d.estado, observaciones: d.observaciones || '',
        clase: original.clase, lado: original.lado,
        comprobanteAsociadoId: d.comprobanteAsociadoId || null,
        items: (d.items || []).map(it => ({ ...it })), total,
      };
      if (original.lado === 'pago') payload.proveedorId = d.proveedorId || null;
      else payload.entidadId = d.entidadId || null;
      // Campos locales/derivados: no viajan al backend (no son columnas reales todavía)
      // pero se mantienen en memoria de sesión para no romper la UI (publicId lo recalcula
      // el trigger; cliente se re-resuelve del FK cuando refresca del server).
      const local = {
        publicId: `${original.clase}-${d.tipo}-${d.puntoVenta}-${d.numero}`,
        comprobanteAsociado: d.comprobanteAsociado, cliente: d.cliente || null,
      };
      const coll = original.clase === 'ND' ? 'notasDebito' : 'notasCredito';
      if (isCreate) {
        const created = MicosStore.create(coll, { ...payload, __nuevo: true });
        Object.assign(created, local);
        onSaved && onSaved(created.id);
      } else {
        if (window.MicosStore) MicosStore.update(coll, original.id, payload);
        Object.assign(original, payload, local);
        setToast(`${original.titulo} ${local.publicId} guardada`);
        setTimeout(() => setToast(null), 3600);
      }
    },
  });

  if (!nota) {
    return (
      <div className="space-y-6 pt-2">
        <button onClick={onBack} className="flex items-center gap-2 text-[11px] font-bold uppercase tracking-[0.12em] cursor-pointer" style={{ color: 'var(--muted-foreground)' }}><IconArrowLeft size={13} />{backLabel || 'Volver a Finanzas'}</button>
        <p className="text-[14px] font-semibold" style={{ color: 'var(--muted-foreground)' }}>No se encontró la nota.</p>
      </div>
    );
  }

  const n = editing && draft ? draft : original;
  const patchItem = (i, field, value) => setDraft((d) => {
    const items = d.items.map((it, k) => {
      if (k !== i) return it;
      const next = { ...it, [field]: value };
      const c = Number(next.cantidad) || 0, u = Number(next.unitario) || 0, b = Number(next.bonifPct) || 0;
      next.total = c * u * (1 - b / 100);
      return next;
    });
    return { ...d, items };
  });
  const addItem = () => setDraft((d) => ({ ...d, items: [...d.items, M.blank()] }));
  const removeItem = (i) => setDraft((d) => ({ ...d, items: d.items.filter((_, k) => k !== i) }));

  const s = M.summary(n.items || []);
  const estOptions = Object.entries((original.lado === 'pago' ? PAGO_ESTADOS : COBRO_ESTADOS) || {}).map(([v, c]) => ({ value: v, label: c.label }));
  const estLabel = ((original.lado === 'pago' ? PAGO_ESTADOS : COBRO_ESTADOS) || {})[n.estado];

  const onPrint = () => {
    const live = resolverNota(original.id) || original;
    const mod = MicosDocNotaMod(live);
    openPrintDoc(mod.fromNota(live, co), {
      mod,
      title: `${live.titulo} ${live.tipo}-${live.puntoVenta}-${live.numero}`,
      subtitle: `${(live.cliente && live.cliente.razonSocial) || live.proveedor || ''}`,
    });
  };
  const actions = buildDocActions({ editing, enterEdit, discardEdit, saveEdit, onPrint,
    onDelete: (!isCreate && editing) ? () => setConfirmDel(true) : undefined });

  const doDelete = () => {
    const coll = original.clase === 'ND' ? 'notasDebito' : 'notasCredito';
    if (window.MicosStore) MicosStore.remove(coll, original.id);
    setConfirmDel(false);
    onBack();
  };

  const subtitle = (
    <React.Fragment>
      <span className="font-bold" style={{ color: 'var(--foreground)' }}>{(n.cliente && n.cliente.razonSocial) || original.proveedor || (editing ? '— elegí cliente —' : '')}</span>
      <span className="mx-1.5 opacity-50">·</span>
      <span style={{ color: 'var(--muted-foreground)' }}>Emitida el {formatDateLong(n.fechaEmision)}</span>
    </React.Fragment>
  );

  const isExento = (n.items || []).every(it => !Number(it.ivaPct));

  return (
    <DocumentShell
      onBack={onBack}
      backLabel={backLabel || 'Volver a Finanzas'}
      eyebrow={original.clase === 'ND' ? `Nota de débito ${original.tipo}` : `Nota de crédito ${original.tipo}`}
      bigId={original.publicId}
      fechaEmision={n.fechaEmision}
      subtitle={subtitle}
      editing={editing}
      isCreate={isCreate}
      toast={toast}
      actions={actions}
    >
      {/* AFIP / CAE */}
      <DocCard>
        <p className="text-[11px] font-bold uppercase tracking-[0.2em] mb-6" style={{ color: 'var(--accent)' }}>Información AFIP</p>
        <div className="grid grid-cols-2 sm:grid-cols-3 gap-x-8 gap-y-6">
          <div className="space-y-2">
            <p className="text-[10.5px] font-bold uppercase tracking-[0.14em]" style={{ color: 'var(--muted-foreground)' }}>Código comprobante</p>
            <p className="text-[17px] font-extrabold leading-none tracking-tight" style={{ color: 'var(--accent)' }}>Cod. {original.codComprobante}</p>
          </div>
          <div className="space-y-2">
            <p className="text-[10.5px] font-bold uppercase tracking-[0.14em]" style={{ color: 'var(--muted-foreground)' }}>CAE</p>
            <p className="text-[17px] font-mono font-extrabold leading-none tracking-tight tabular-nums" style={{ color: original.cae ? 'var(--foreground)' : 'color-mix(in oklab, var(--muted-foreground) 60%, transparent)' }}>{original.cae || '— pendiente —'}</p>
          </div>
          <div className="space-y-2">
            <p className="text-[10.5px] font-bold uppercase tracking-[0.14em]" style={{ color: 'var(--muted-foreground)' }}>Vto. CAE</p>
            <p className="text-[17px] font-mono font-extrabold leading-none tracking-tight tabular-nums" style={{ color: original.caeVto ? 'var(--foreground)' : 'color-mix(in oklab, var(--muted-foreground) 60%, transparent)' }}>{original.caeVto ? formatDate(original.caeVto) : '—'}</p>
          </div>
        </div>
      </DocCard>

      {/* Meta strip */}
      <DocMetaStrip editing={editing} items={[
        { label: 'Comprobante', value: original.titulo },
        { label: 'Tipo', value: editing ? draft.tipo : original.tipo, mono: true, accent: true, editable: editing, inputType: 'select', options: ['A', 'B'], onChange: (v) => patch('tipo', v) },
        // P17a (recorrido §10, mismo criterio que factura.jsx): Punto venta y
        // Número son fiscales/AFIP en NC/ND igual que en Factura — antes acá
        // quedaban editables (asimetría, no estaba en el alcance original de
        // P8) — se bloquean para que las 3 familias fiscales (factura/NC/ND)
        // sean consistentes.
        { label: 'Punto venta', value: original.puntoVenta, mono: true },
        { label: 'Número', value: original.numero, mono: true, accent: true },
        { label: 'Emisión', value: editing ? draft.fechaEmision : formatDate(original.fechaEmision), mono: true, editable: editing, inputType: 'date', onChange: (v) => patch('fechaEmision', v) },
        { label: 'Vencimiento', value: editing ? draft.fechaVencimiento : formatDate(original.fechaVencimiento), mono: true, editable: editing, inputType: 'date', onChange: (v) => patch('fechaVencimiento', v) },
        // En cobros el "Comp. asociado" lo maneja el picker de facturas de abajo (FK real):
        // acá va SOLO como lectura del número elegido. En pagos sigue como texto libre editable
        // (su FK apuntaría a `facturas`, que no aplica del lado pago).
        { label: 'Comp. asociado', value: editing ? (draft.comprobanteAsociado || '—') : (compAsocResuelto || '—'), mono: true, accent: !!(editing ? draft.comprobanteAsociado : compAsocResuelto), editable: editing && original.lado === 'pago', onChange: (v) => patch('comprobanteAsociado', v) },
        { label: 'Estado', value: editing ? draft.estado : (estLabel ? estLabel.label : n.estado), editable: editing, inputType: 'select', options: estOptions.map(o => o.value), onChange: (v) => patch('estado', v) },
      ]} />

      {/* Comprobante asociado (solo cobros): selector real sobre la FK comprobante_asociado_id
          → facturas.id. Reemplaza el input de texto libre del meta strip, que solo vivía en
          memoria de sesión. En pagos no se muestra: la FK apunta a `facturas` (lado cobro). */}
      {editing && original.lado !== 'pago' && window.ComprobanteCombobox && (
        <DocCard>
          <p className="text-[11px] font-bold uppercase tracking-[0.2em] mb-1.5" style={{ color: 'var(--accent)' }}>Comprobante asociado</p>
          <p className="text-[12.5px] mb-4" style={{ color: 'var(--muted-foreground)' }}>Elegí la factura que esta nota ajusta — queda vinculada por su comprobante real, no como texto suelto.</p>
          {draft.comprobanteAsociado && (
            <div className="flex items-center gap-3 mb-3 px-4 py-3 rounded-xl" style={{ background: 'color-mix(in oklab, var(--surface) 50%, transparent)', border: '1px solid color-mix(in oklab, var(--border) 45%, transparent)' }}>
              <span className="font-mono text-[13px] font-bold flex-1 min-w-0 truncate" style={{ color: 'var(--foreground)' }}>{draft.comprobanteAsociado}</span>
              <button type="button" onClick={() => setDraft((d) => ({ ...d, comprobanteAsociado: '', comprobanteAsociadoId: null }))} title="Quitar" className="inline-flex items-center justify-center rounded-md cursor-pointer flex-shrink-0" style={{ width: 30, height: 30, color: 'var(--muted-foreground)' }}>
                <IconX size={14} />
              </button>
            </div>
          )}
          <window.ComprobanteCombobox
            lado="cobro"
            onlyKinds={['factura']}
            excludeKeys={[]}
            lockedLetra=""
            onPick={(c) => setDraft((d) => ({ ...d, comprobanteAsociadoId: c.id, comprobanteAsociado: c.numero }))}
          />
        </DocCard>
      )}

      {/* Emisor + Cliente */}
      <DocCard className="relative">
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
          <PartyBlock eyebrow="Emisor" name={co.nombre} sub={co.situacionIva} fields={buildEmisorFields(co)} />
          <PartyBlock eyebrow={original.lado === 'pago' ? 'Proveedor' : 'Cliente'} name={(n.cliente && n.cliente.razonSocial) || original.proveedor || (editing ? '— elegí uno —' : '')} sub={(n.cliente && n.cliente.condicionIva) || 'Responsable Inscripto'} fields={buildClienteFieldsCompacto(n.cliente)} />
        </div>
        {editing && (
          <button onClick={() => setProvPicker(true)} title={original.lado === 'pago' ? 'Elegir proveedor' : 'Elegir cliente'} className="party-edit-btn absolute" style={{ top: 16, right: 16 }} type="button">
            <IconPencil size={13} />
          </button>
        )}
      </DocCard>

      {/* Ítems + Totales */}
      <DocCard editing={editing}>
        <ItemsTable
          items={n.items || []}
          showBonif showIva
          editing={editing}
          onItemChange={patchItem} onItemRemove={removeItem} onAdd={addItem}
        />
        <Totals
          subtotal={s.totalBase}
          bonificaciones={s.bonifTotal}
          ivaLines={s.ivaLines}
          total={s.total}
          hideIva={isExento}
          importeLetras={original.importeLetras}
        />
      </DocCard>

      <ObservacionesCard editing={editing} value={editing ? draft.observaciones : original.observaciones} onChange={(v) => patch('observaciones', v)} />

      {provPicker && window.PartySelectorModal && (
        <window.PartySelectorModal
          type={original.lado === 'pago' ? 'proveedor' : 'entidad'}
          open={true}
          onClose={() => setProvPicker(false)}
          onPick={(obj) => {
            // El objeto lo elige de ENTIDADES/PROVEEDORES (tiene `.id` real) — lo guardamos
            // en entidadId/proveedorId (FK real que sí persiste) además del snapshot
            // `cliente` (solo para pintar la tarjeta mientras dura la sesión).
            if (obj) setDraft((d) => ({
              ...d,
              cliente: {
                razonSocial: obj.razonSocial || obj.nombre || '',
                condicionIva: obj.condicionIva || 'Responsable Inscripto',
                cuit: obj.cuit || '',
                domicilio: obj.domicilio || '',
                localidad: obj.localidad || '',
                condicionVenta: obj.condicionVenta || 'Cuenta corriente',
              },
              ...(original.lado === 'pago' ? { proveedorId: obj.id || null } : { entidadId: obj.id || null }),
            }));
            setProvPicker(false);
          }}
        />
      )}

      {confirmDel && window.ConfirmDeleteModal && (
        <window.ConfirmDeleteModal
          title={`¿Eliminar ${original.titulo || 'la nota'}?`}
          itemName={original.publicId}
          description="Se va a borrar este comprobante de Finanzas. Esta acción no se puede deshacer."
          confirmLabel="Sí, eliminar"
          onCancel={() => setConfirmDel(false)}
          onConfirm={doDelete}
        />
      )}
    </DocumentShell>
  );
}

Object.assign(window, { NotaScreen });
