// ─── Directorio — modal genérico de alta/edición de sub-recursos ───────────
// DECISIÓN 1 (ARBITRAJES.md ítem 1, 06/07/2026 — CRUD real de los sub-recursos del
// directorio: entidad_contacto/entidad_convenio/medico_entidad). `DirSubResourceModal` es
// el motor único de alta/edición para los 3 — el chrome (overlay+blur, card, header con
// ícono+eyebrow+título+X, footer Cancelar/Guardar) es el MISMO de `RecordFormModal`
// (ui/record-form.jsx) y `PartySelectorModal` (ui/party-selector.jsx), copiado carácter a
// carácter (mismos tokens, sin inventar nada nuevo — CLAUDE.md §0/§2). Los callers
// (screens/directorio/entidades.jsx y medicos.jsx) son dueños del fetch real (POST/PATCH
// contra entidad-contactos/entidad-convenios/medico-entidades) — este componente solo arma
// el form declarativo + la validación de `required`, mismo contrato que `fields` de
// ui/record-form.jsx (RFField) y ui/party-selector.jsx (ModalField).
// `DirRowActions` es el par lápiz+tacho (mismo tamaño/hover/colores que los íconos de fila
// de FileUploadCard, ui/doc-kit-edit.jsx) que ahora llevan los renglones de contacto/
// convenio/centro en las fichas de Entidad/Médico. Expone a window: DirSubResourceModal,
// DirRowActions. Consume window.AltaSelect (ui/primitives.jsx), Icon* (ui/icons.jsx).
// Partido de ui/dir-kit.jsx (que ya rondaba el techo de líneas) por tema: layout de ficha
// vs. motor de modal — AGENTS.md "un archivo = un tema".

const { useState: _useStateDSM, useEffect: _useEffectDSM } = React;

// ─── Par de acciones lápiz+tacho de un renglón de sub-recurso ────────────
// `onEdit` es opcional (medico_entidad hoy solo edita `nota`; si un sub-recurso no tiene
// nada editable aparte de borrarse, no se pasa).
function DirRowActions({ onEdit, onDelete, editTitle = 'Editar', deleteTitle = 'Eliminar' }) {
  return (
    <div className="flex items-center gap-1">
      {onEdit && (
        <button type="button" onClick={onEdit} title={editTitle}
          className="inline-flex items-center justify-center rounded-md transition-colors cursor-pointer"
          style={{ width: 30, height: 30, color: 'var(--muted-foreground)' }}
          onMouseEnter={(e) => { e.currentTarget.style.color = 'var(--accent)'; e.currentTarget.style.background = 'color-mix(in oklab, var(--accent) 10%, transparent)'; }}
          onMouseLeave={(e) => { e.currentTarget.style.color = 'var(--muted-foreground)'; e.currentTarget.style.background = 'transparent'; }}>
          <IconPencil size={13} />
        </button>
      )}
      <button type="button" onClick={onDelete} title={deleteTitle}
        className="inline-flex items-center justify-center rounded-md transition-colors cursor-pointer"
        style={{ width: 30, height: 30, color: 'var(--destructive)' }}
        onMouseEnter={(e) => { e.currentTarget.style.background = 'color-mix(in oklab, var(--destructive) 14%, transparent)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
        <IconTrash size={13} />
      </button>
    </div>
  );
}

// ─── Campo del modal genérico (scope de módulo — regla §5 CLAUDE.md: nunca
// definido dentro del render de otro componente, si no React remonta y se
// pierde el foco al tipear) ───────────────────────────────────────────────
function DirModalField({ f, value, onChange, error }) {
  let control;
  if (f.type === 'select') {
    const opts = typeof f.options === 'function' ? f.options() : (f.options || []);
    control = (
      <AltaSelect value={value ?? ''} onChange={(e) => onChange(f.key, e.target.value)}>
        <option value="">Seleccionar…</option>
        {opts.map((o) => {
          const val = typeof o === 'string' ? o : o.value;
          const lab = typeof o === 'string' ? o : o.label;
          return <option key={val} value={val}>{lab}</option>;
        })}
      </AltaSelect>
    );
  } else if (f.type === 'textarea') {
    control = (
      <textarea className="input" rows={f.rows || 3} placeholder={f.placeholder || ''}
        value={value ?? ''} onChange={(e) => onChange(f.key, e.target.value)}
        style={{ minHeight: 0, height: 'auto', paddingTop: 8, paddingBottom: 8, resize: 'vertical', lineHeight: 1.5 }} />
    );
  } else {
    control = (
      <input className={`input${f.mono ? ' font-mono tabular-nums' : ''}`}
        type={f.type === 'date' ? 'date' : 'text'} placeholder={f.placeholder || ''}
        value={value ?? ''} onChange={(e) => onChange(f.key, e.target.value)} />
    );
  }
  return (
    <div style={{ gridColumn: f.span ? '1 / -1' : 'auto' }}>
      <label className="block text-[11px] font-bold uppercase tracking-[0.12em] mb-1.5" style={{ color: 'var(--muted-foreground)' }}>
        {f.label}{f.required && <span style={{ color: 'var(--accent)' }}>*</span>}
      </label>
      {control}
      {error && <p className="text-[11px] font-semibold mt-1" style={{ color: 'var(--danger)' }}>{error}</p>}
    </div>
  );
}

// ─── Modal genérico de alta/edición de un sub-recurso del Directorio ────────
// `extra`: nodo opcional que se renderiza DESPUÉS de los campos (hoy: FileUploadCard del
// convenio, ver entidades.jsx — sesión, mismo patrón que el resto del bundle; ver notasMerge
// del paquete para el día que la Decisión 9/adjuntos aterrice persistencia real).
function DirSubResourceModal({ open, onClose, icon: Icon, eyebrow, title, fields, initial, onSave, saving, error, extra }) {
  const [form, setForm] = _useStateDSM(initial || {});
  const [touched, setTouched] = _useStateDSM(false);

  _useEffectDSM(() => {
    if (!open) return undefined;
    setForm(initial || {});
    setTouched(false);
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = prev; };
  }, [open]);

  if (!open) return null;
  const set = (k, v) => setForm((f) => ({ ...f, [k]: v }));

  const handleSubmit = (e) => {
    e.preventDefault();
    setTouched(true);
    for (const f of fields) {
      if (f.required && !String(form[f.key] ?? '').trim()) return;
    }
    onSave(form);
  };

  return (
    <div
      className="fixed inset-0 z-50 flex items-start sm:items-center justify-center p-4 sm:p-6 overflow-y-auto"
      style={{ background: 'color-mix(in oklab, #0a1418 62%, transparent)', backdropFilter: 'blur(4px)' }}
      onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}
    >
      <div
        className="w-full max-w-lg rounded-2xl my-auto animate-fade-in-up"
        style={{ background: 'var(--card)', border: '1px solid color-mix(in oklab, var(--border) 65%, transparent)', boxShadow: '0 30px 80px -20px rgba(8, 20, 24, 0.55)' }}
        onMouseDown={(e) => e.stopPropagation()}
      >
        <div className="flex items-start justify-between gap-4 px-6 pt-5 pb-4"
          style={{ borderBottom: '1px solid color-mix(in oklab, var(--border) 55%, transparent)' }}>
          <div className="flex items-center gap-3 min-w-0">
            {Icon && (
              <span className="inline-flex items-center justify-center rounded-lg flex-shrink-0"
                style={{ width: 34, height: 34, background: 'color-mix(in oklab, var(--accent) 12%, transparent)', color: 'var(--accent)' }}>
                <Icon size={16} />
              </span>
            )}
            <div className="min-w-0">
              <p className="text-[11px] font-bold uppercase tracking-[0.16em]" style={{ color: 'var(--accent)' }}>{eyebrow}</p>
              <h2 className="text-[18px] font-extrabold tracking-tight" style={{ color: 'var(--foreground)' }}>{title}</h2>
            </div>
          </div>
          <button type="button" onClick={onClose}
            className="inline-flex items-center justify-center flex-shrink-0 rounded-lg transition-colors cursor-pointer"
            style={{ width: 34, height: 34, border: '1px solid color-mix(in oklab, var(--border) 60%, transparent)', color: 'var(--muted-foreground)' }}
            aria-label="Cerrar">
            <IconX size={16} />
          </button>
        </div>
        <form onSubmit={handleSubmit}>
          <div className="px-6 py-5 grid grid-cols-2 gap-x-4 gap-y-4" style={{ maxHeight: '62vh', overflowY: 'auto' }}>
            {fields.map((f) => (
              <DirModalField key={f.key} f={f} value={form[f.key]} onChange={set}
                error={touched && f.required && !String(form[f.key] ?? '').trim() ? 'Requerido.' : null} />
            ))}
            {extra}
            {error && (
              <p className="text-[12px] font-semibold" style={{ gridColumn: '1 / -1', color: 'var(--danger)' }}>{error}</p>
            )}
          </div>
          <div className="flex items-center justify-end gap-2.5 px-6 py-4" style={{ borderTop: '1px solid color-mix(in oklab, var(--border) 55%, transparent)' }}>
            <button type="button" className="btn btn-outline" onClick={onClose} disabled={saving}>Cancelar</button>
            <button type="submit" className="btn btn-primary" style={{ boxShadow: 'none' }} disabled={saving}>
              {saving ? 'Guardando…' : 'Guardar'}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

Object.assign(window, { DirSubResourceModal, DirRowActions });
