// ui.jsx — librería de UI compartida para CIECAV · HCE
const { useState, useRef, useEffect } = React;

const ICONS = {
  dashboard: "M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z",
  patients: "M16 11a4 4 0 1 0-4-4 4 4 0 0 0 4 4zm-8 1a3 3 0 1 0-3-3 3 3 0 0 0 3 3zm0 2c-2.7 0-5 1.3-5 3v2h6v-2c0-.9.4-1.7 1-2.4A7 7 0 0 0 8 14zm8 0c-2.7 0-8 1.3-8 4v2h16v-2c0-2.7-5.3-4-8-4z",
  search: "M21 21l-4.3-4.3M11 18a7 7 0 1 1 0-14 7 7 0 0 1 0 14z",
  agenda: "M7 3v3m10-3v3M4 8h16M5 5h14a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1z",
  doc: "M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8l-5-5zm0 0v5h5M8 13h8M8 17h6",
  folder: "M3 7a1 1 0 0 1 1-1h5l2 2h8a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7z",
  pdf: "M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8l-5-5zm0 0v5h5M8 14h1.5a1.5 1.5 0 0 1 0 3H8v-3zm0 0v4m5-4v4m0-4h2m-2 2h1.5",
  ai: "M12 2l1.6 4.4L18 8l-4.4 1.6L12 14l-1.6-4.4L6 8l4.4-1.6L12 2zM5 16l.8 2.2L8 19l-2.2.8L5 22l-.8-2.2L2 19l2.2-.8L5 16zm14 0l.8 2.2L22 19l-2.2.8L19 22l-.8-2.2L16 19l2.2-.8L19 16z",
  heart: "M12 21s-7-4.5-9.5-9A5 5 0 0 1 12 6a5 5 0 0 1 9.5 6c-2.5 4.5-9.5 9-9.5 9z",
  plus: "M12 5v14M5 12h14",
  chevron: "M9 6l6 6-6 6",
  chevronDown: "M6 9l6 6 6-6",
  bell: "M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.7 21a2 2 0 0 1-3.4 0",
  alert: "M12 9v4m0 4h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z",
  check: "M20 6L9 17l-5-5",
  checkCircle: "M9 12l2 2 4-4m6 2a9 9 0 1 1-18 0 9 9 0 0 1 18 0z",
  x: "M18 6L6 18M6 6l12 12",
  mic: "M12 2a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3zM5 11a7 7 0 0 0 14 0M12 18v3",
  pill: "M10.5 20.5a5 5 0 0 1-7-7l6-6a5 5 0 0 1 7 7l-6 6zM8 8l8 8",
  vitals: "M3 12h4l2-7 4 14 2-7h6",
  edit: "M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z",
  print: "M6 9V3h12v6M6 18H4a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-2M6 14h12v6H6v-6z",
  sign: "M3 17s2-4 5-4 4 3 7 3 4-4 4-4M3 21h18",
  shield: "M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3z",
  logout: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4m7 14l5-5-5-5m5 5H9",
  filter: "M3 4h18l-7 8v6l-4 2v-8L3 4z",
  clock: "M12 7v5l3 2m6-2a9 9 0 1 1-18 0 9 9 0 0 1 18 0z",
  user: "M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm-7 9a7 7 0 0 1 14 0",
  attach: "M21 11l-9 9a5 5 0 0 1-7-7l9-9a3.5 3.5 0 0 1 5 5l-9 9a2 2 0 0 1-3-3l8-8",
  lab: "M9 3h6M10 3v6L5 19a2 2 0 0 0 2 3h10a2 2 0 0 0 2-3l-5-10V3",
  back: "M19 12H5m7 7l-7-7 7-7",
  stethoscope: "M6 3v6a4 4 0 0 0 8 0V3M4 3h2m6 0h2m-4 13a5 5 0 0 0 5 5 4 4 0 0 0 4-4v-2m0 0a2 2 0 1 0 0-4 2 2 0 0 0 0 4z",
  lock: "M18 11H6a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2zM8 11V7a4 4 0 0 1 8 0v4",
  add: "M12 5v14M5 12h14",
};

function Icon({ name, size = 20, stroke = 2, fill = false, style = {} }) {
  const d = ICONS[name];
  if (fill) {
    return <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" style={style} aria-hidden="true"><path d={d} /></svg>;
  }
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={style} aria-hidden="true"><path d={d} /></svg>;
}

function Btn({ children, variant = "primary", size = "md", icon, onClick, type = "button", style = {}, disabled, title }) {
  const sizes = { sm: { padding: "6px 10px", fontSize: 13, gap: 6 }, md: { padding: "9px 14px", fontSize: 14, gap: 8 }, lg: { padding: "12px 20px", fontSize: 15, gap: 9 } };
  const variants = {
    primary: { background: "var(--accent)", color: "#fff", border: "1px solid var(--accent)" },
    soft: { background: "var(--accent-soft)", color: "var(--accent-ink)", border: "1px solid transparent" },
    ghost: { background: "transparent", color: "var(--ink-2)", border: "1px solid var(--line)" },
    danger: { background: "var(--danger-soft)", color: "var(--danger)", border: "1px solid transparent" },
    dark: { background: "var(--ink)", color: "var(--surface)", border: "1px solid var(--ink)" },
  };
  return (
    <button type={type} onClick={onClick} disabled={disabled} title={title} className="g-btn"
      style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", borderRadius: 9, fontWeight: 600, cursor: disabled ? "not-allowed" : "pointer", opacity: disabled ? 0.5 : 1, fontFamily: "inherit", transition: "filter .15s, transform .05s", ...sizes[size], ...variants[variant], ...style }}>
      {icon && <Icon name={icon} size={size === "sm" ? 15 : 17} />}
      {children}
    </button>
  );
}

function Badge({ children, tone = "neutral", dot = false, style = {} }) {
  const tones = {
    neutral: { bg: "var(--chip)", fg: "var(--ink-2)" },
    blue: { bg: "color-mix(in oklch, var(--accent) 12%, transparent)", fg: "var(--accent-ink)" },
    green: { bg: "color-mix(in oklch, var(--ok) 16%, transparent)", fg: "var(--ok-ink)" },
    amber: { bg: "color-mix(in oklch, var(--warn) 20%, transparent)", fg: "var(--warn-ink)" },
    red: { bg: "var(--danger-soft)", fg: "var(--danger)" },
    purple: { bg: "color-mix(in oklch, #7c3aed 14%, transparent)", fg: "#6d28d9" },
  };
  const t = tones[tone] || tones.neutral;
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: "3px 9px", borderRadius: 999, fontSize: 12, fontWeight: 600, letterSpacing: ".01em", background: t.bg, color: t.fg, whiteSpace: "nowrap", ...style }}>
      {dot && <span style={{ width: 6, height: 6, borderRadius: 99, background: "currentColor" }} />}
      {children}
    </span>
  );
}

function Card({ children, title, subtitle, icon, action, pad = true, style = {}, bodyStyle = {} }) {
  return (
    <section style={{ background: "var(--surface)", border: "1px solid var(--line)", borderRadius: 14, boxShadow: "var(--shadow)", overflow: "hidden", display: "flex", flexDirection: "column", ...style }}>
      {title && (
        <header style={{ display: "flex", alignItems: "center", gap: 10, padding: "14px 18px", borderBottom: "1px solid var(--line)" }}>
          {icon && <span style={{ color: "var(--accent)", display: "flex" }}><Icon name={icon} size={18} /></span>}
          <div style={{ flex: 1, minWidth: 0 }}>
            <h3 style={{ margin: 0, fontSize: 14.5, fontWeight: 700, color: "var(--ink)", letterSpacing: "-.01em" }}>{title}</h3>
            {subtitle && <p style={{ margin: "2px 0 0", fontSize: 12.5, color: "var(--ink-3)" }}>{subtitle}</p>}
          </div>
          {action}
        </header>
      )}
      <div style={{ padding: pad ? 18 : 0, flex: 1, ...bodyStyle }}>{children}</div>
    </section>
  );
}

function Field({ label, children, hint, required, full, style = {} }) {
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 6, gridColumn: full ? "1 / -1" : "auto", ...style }}>
      {label && <span style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink-2)" }}>{label}{required && <span style={{ color: "var(--danger)" }}> *</span>}</span>}
      {children}
      {hint && <span style={{ fontSize: 11.5, color: "var(--ink-3)" }}>{hint}</span>}
    </label>
  );
}

const inputStyle = {
  width: "100%", padding: "9px 11px", fontSize: 14, fontFamily: "inherit",
  background: "var(--field)", color: "var(--ink)", border: "1px solid var(--line-2)",
  borderRadius: 9, outline: "none", boxSizing: "border-box", transition: "border-color .15s, box-shadow .15s",
};

function TextInput(props) { return <input {...props} className="g-input" style={{ ...inputStyle, ...(props.style || {}) }} />; }
function TextArea(props) { return <textarea {...props} className="g-input" style={{ ...inputStyle, resize: "vertical", minHeight: 84, lineHeight: 1.5, ...(props.style || {}) }} />; }
function Select({ children, ...props }) { return <select {...props} className="g-input" style={{ ...inputStyle, cursor: "pointer", ...(props.style || {}) }}>{children}</select>; }

function Avatar({ text, color = "#64748b", size = 40 }) {
  return (
    <span style={{ width: size, height: size, borderRadius: size * 0.28, background: color, color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, fontWeight: 700, fontSize: size * 0.36, letterSpacing: ".02em" }}>{text}</span>
  );
}

function Modal({ open, onClose, title, children, width = 560, footer }) {
  useEffect(() => {
    const h = (e) => e.key === "Escape" && onClose && onClose();
    if (open) window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [open]);
  if (!open) return null;
  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 200, background: "color-mix(in oklch, var(--ink) 45%, transparent)", display: "flex", alignItems: "flex-start", justifyContent: "center", padding: "6vh 20px", backdropFilter: "blur(3px)", animation: "g-fade .15s ease" }}>
      <div onClick={(e) => e.stopPropagation()} style={{ background: "var(--surface)", borderRadius: 16, width: "100%", maxWidth: width, boxShadow: "0 24px 60px -12px rgba(0,0,0,.35)", border: "1px solid var(--line)", maxHeight: "88vh", display: "flex", flexDirection: "column", animation: "g-pop .2s ease" }}>
        <header style={{ display: "flex", alignItems: "center", padding: "16px 20px", borderBottom: "1px solid var(--line)" }}>
          <h3 style={{ margin: 0, fontSize: 16, fontWeight: 700, flex: 1, color: "var(--ink)" }}>{title}</h3>
          <button onClick={onClose} className="g-iconbtn" style={{ border: "none", background: "transparent", cursor: "pointer", color: "var(--ink-3)", display: "flex", padding: 4, borderRadius: 8 }}><Icon name="x" size={20} /></button>
        </header>
        <div style={{ padding: 20, overflow: "auto", flex: 1 }}>{children}</div>
        {footer && <footer style={{ display: "flex", justifyContent: "flex-end", gap: 10, padding: "14px 20px", borderTop: "1px solid var(--line)" }}>{footer}</footer>}
      </div>
    </div>
  );
}

function DxSearch({ onPick, placeholder, aiSuggestions = [], defaultVersion = "CIE-10" }) {
  const [q, setQ] = useState("");
  const [open, setOpen] = useState(false);
  const [ver, setVer] = useState(defaultVersion);
  const catalog = ver === "CIE-11" ? (window.CIE11 || []) : (window.CIE10 || []);
  const ph = placeholder || `Buscar diagnóstico o código ${ver}…`;
  const norm = (s) => s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
  const nq = norm(q.trim());
  let results = [];
  if (nq.length >= 1) {
    results = catalog
      .map((d) => {
        const code = norm(d.c), name = norm(d.n);
        let score = 0;
        if (code.startsWith(nq)) score += 100;
        else if (code.includes(nq)) score += 40;
        if (name.startsWith(nq)) score += 50;
        else if (name.includes(nq)) score += 25;
        nq.split(/\s+/).forEach((w) => { if (w && name.includes(w)) score += 8; });
        return { ...d, score: score + (d.freq || 0) };
      })
      .filter((d) => d.score > 5)
      .sort((a, b) => b.score - a.score)
      .slice(0, 8);
  }
  const pick = (d) => { onPick && onPick({ ...d, version: ver }); setQ(""); setOpen(false); };
  return (
    <div style={{ position: "relative" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
        <span style={{ fontSize: 12, fontWeight: 600, color: "var(--ink-3)" }}>Estándar:</span>
        {["CIE-10", "CIE-11"].map((v) => (
          <button key={v} onClick={() => { setVer(v); setQ(""); }}
            style={{ padding: "4px 14px", borderRadius: 20, border: `1.5px solid ${ver === v ? "var(--accent)" : "var(--line)"}`, background: ver === v ? "var(--accent)" : "transparent", color: ver === v ? "#fff" : "var(--ink-3)", fontSize: 12.5, fontWeight: 700, cursor: "pointer", transition: "all .15s" }}>
            {v}
          </button>
        ))}
      </div>
      <div style={{ position: "relative" }}>
        <span style={{ position: "absolute", left: 11, top: "50%", transform: "translateY(-50%)", color: "var(--ink-3)", display: "flex" }}><Icon name="search" size={17} /></span>
        <input value={q} placeholder={ph} className="g-input"
          onChange={(e) => { setQ(e.target.value); setOpen(true); }}
          onFocus={() => setOpen(true)}
          onBlur={() => setTimeout(() => setOpen(false), 180)}
          style={{ ...inputStyle, paddingLeft: 36 }} />
      </div>
      {open && (q.trim() || aiSuggestions.length > 0) && (
        <div style={{ position: "absolute", top: "calc(100% + 6px)", left: 0, right: 0, zIndex: 50, background: "var(--surface)", border: "1px solid var(--line)", borderRadius: 12, boxShadow: "0 16px 40px -8px rgba(0,0,0,.25)", overflow: "hidden", maxHeight: 340, overflowY: "auto" }}>
          {!q.trim() && aiSuggestions.length > 0 && (
            <div style={{ padding: "8px 12px", display: "flex", alignItems: "center", gap: 6, fontSize: 11.5, fontWeight: 700, color: "#6d28d9", background: "color-mix(in oklch, #7c3aed 7%, transparent)", letterSpacing: ".03em", textTransform: "uppercase" }}>
              <Icon name="ai" size={14} /> Sugeridos por IA según el cuadro clínico
            </div>
          )}
          {(q.trim() ? results : aiSuggestions).map((d) => (
            <button key={d.c} onMouseDown={() => pick(d)} className="g-result"
              style={{ display: "flex", alignItems: "center", gap: 12, width: "100%", textAlign: "left", padding: "10px 12px", border: "none", background: "transparent", cursor: "pointer", borderBottom: "1px solid var(--line)" }}>
              <span style={{ fontFamily: "var(--mono)", fontSize: 12.5, fontWeight: 700, color: "var(--accent)", background: "var(--accent-soft)", padding: "3px 7px", borderRadius: 6, minWidth: 54, textAlign: "center" }}>{d.c}</span>
              <span style={{ flex: 1, fontSize: 13.5, color: "var(--ink)" }}>{d.n}</span>
              {d.matchPct && <Badge tone="purple">{d.matchPct}%</Badge>}
            </button>
          ))}
          {q.trim() && results.length === 0 && <div style={{ padding: 16, fontSize: 13, color: "var(--ink-3)", textAlign: "center" }}>Sin coincidencias para "{q}" en {ver}.</div>}
        </div>
      )}
    </div>
  );
}

// Backward compat alias
const CIE10Search = (props) => React.createElement(DxSearch, { ...props, defaultVersion: "CIE-10" });

function Stat({ label, value, icon, tone = "blue", sub }) {
  const tones = { blue: "var(--accent)", green: "var(--ok)", amber: "var(--warn)", red: "var(--danger)" };
  const col = tones[tone] || tones.blue;
  return (
    <div style={{ background: "var(--surface)", border: "1px solid var(--line)", borderRadius: 14, padding: "16px 18px", boxShadow: "var(--shadow)", display: "flex", flexDirection: "column", gap: 10 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <span style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink-3)" }}>{label}</span>
        <span style={{ color: col, background: `color-mix(in oklch, ${col} 13%, transparent)`, borderRadius: 9, padding: 7, display: "flex" }}>
          <Icon name={icon} size={18} />
        </span>
      </div>
      <div style={{ fontSize: 28, fontWeight: 800, color: "var(--ink)", letterSpacing: "-.02em", lineHeight: 1 }}>{value}</div>
      {sub && <span style={{ fontSize: 12, color: "var(--ink-3)" }}>{sub}</span>}
    </div>
  );
}

Object.assign(window, { Icon, Btn, Badge, Card, Field, TextInput, TextArea, Select, Avatar, Modal, DxSearch, CIE10Search, Stat, inputStyle });
