/*
  components.jsx — UI building blocks for Zurullitos Armados
*/

const { useState, useEffect, useRef, useCallback, useMemo, createContext, useContext } = React;

function classNames(...args) {
  return args.filter(Boolean).join(' ');
}

/* ---------- NIO formatting ---------- */
function normalizeNIO(s) {
  if (!s) return '';
  const digits = String(s).replace(/[^0-9]/g, '').slice(0, 12);
  if (digits.length <= 5) return digits;
  if (digits.length <= 7) return digits.slice(0, 5) + '-' + digits.slice(5);
  return digits.slice(0, 5) + '-' + digits.slice(5, 7) + '-' + digits.slice(7);
}
function isValidNIO(s) { return /^\d{5}-\d{2}-\d{5}$/.test(s); }

/* ---------- Global CSS injected once ---------- */
const COMPONENT_CSS = `
/* Paper card */
.paper {
  position: relative;
  background: var(--paper);
  color: var(--ink);
  border-radius: 2px;
  box-shadow:
    0 1px 0 rgba(0,0,0,0.25),
    0 16px 30px -12px rgba(0,0,0,0.45),
    inset 0 0 0 1px rgba(0,0,0,0.06);
}
.paper::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg, transparent 0 28px, rgba(26,31,20,0.04) 28px 29px),
    radial-gradient(ellipse at 80% 0%, rgba(0,0,0,0.06), transparent 50%),
    radial-gradient(ellipse at 0% 100%, rgba(0,0,0,0.06), transparent 50%);
  mix-blend-mode: multiply;
}
.paper-inner {
  position: relative;
  z-index: 1;
  padding: clamp(20px, 4vw, 36px);
}
.paper-edge {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--paper-edge);
  pointer-events: none;
  opacity: 0.7;
}
.paper-tape {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%) rotate(-2deg);
  width: 110px;
  height: 26px;
  background: var(--tape);
  opacity: 0.85;
  box-shadow: 0 1px 0 rgba(0,0,0,0.15);
}
.paper-tape::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(90deg, transparent 0 8px, rgba(255,255,255,0.15) 8px 9px);
  opacity: 0.5;
}

/* Stamp */
.stamp { display: inline-block; transform-origin: center; filter: contrast(1.05); }
.stamp-inner {
  position: relative;
  padding: 12px 22px;
  border: 5px double currentColor;
  font-family: var(--font-display);
  font-weight: 900;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  opacity: 0.88;
}
.stamp-inner::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(circle at 20% 30%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 70% 80%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 50% 50%, rgba(255,255,255,0.4) 0 1px, transparent 2px);
  background-size: 7px 7px, 11px 11px, 5px 5px;
  mix-blend-mode: screen;
  pointer-events: none;
  opacity: 0.6;
}
.stamp-label { font-size: 38px; line-height: 0.95; }
.stamp-sub { margin-top: 4px; font-size: 14px; letter-spacing: 0.18em; opacity: 0.95; }

/* Pill */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
}

/* Stat */
.stat { display: flex; flex-direction: column; gap: 4px; padding: 8px 0; }
.stat-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.stat-value {
  font-family: var(--font-ui);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.15;
}
.stat-value.mono { font-family: var(--font-mono); font-weight: 500; }
.stat-hint { font-size: 12px; color: var(--muted); font-style: italic; }

/* Rule */
.rule {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  margin: 18px 0;
}
.rule span { flex: 1; height: 1px; background: currentColor; opacity: 0.18; }
.rule em {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-style: normal;
  opacity: 0.55;
}

/* Banner */
.banner {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 12px 14px;
  border-left: 3px solid;
  border-radius: 2px;
  font-size: 14px;
  line-height: 1.5;
}
.banner-icon { flex-shrink: 0; margin-top: 2px; opacity: 0.8; }

/* Toasts */
.toasts {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 8px;
  z-index: 200; pointer-events: none;
}
.toast {
  background: var(--ink);
  color: var(--paper);
  padding: 10px 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  box-shadow: 0 6px 20px rgba(0,0,0,0.35);
  animation: toast-in 0.25s ease-out;
  border-left: 3px solid var(--reserva);
}
.toast-success { border-color: var(--plaza); }
.toast-error { border-color: var(--rechazo); }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
`;
(function injectCSS() {
  if (document.getElementById('za-components-css')) return;
  const el = document.createElement('style');
  el.id = 'za-components-css';
  el.textContent = COMPONENT_CSS;
  document.head.appendChild(el);
})();

/* ---------- Paper card ---------- */
function Paper({ children, tilt = 0, tape = false, edge = true, style, className, ...rest }) {
  return (
    <div
      className={classNames('paper', className)}
      style={{ transform: tilt ? `rotate(${tilt}deg)` : undefined, ...style }}
      {...rest}
    >
      {tape && <span className="paper-tape" aria-hidden="true" />}
      <div className="paper-inner">{children}</div>
      {edge && <span className="paper-edge" aria-hidden="true" />}
    </div>
  );
}

/* ---------- Stamp ---------- */
function Stamp({ label, sublabel, tone = 'plaza', rotate = -7, size = 'lg', style }) {
  const palette = {
    plaza:   { border: 'var(--plaza)',   color: 'var(--plaza-deep)' },
    reserva: { border: 'var(--reserva)', color: 'var(--reserva-deep)' },
    rechazo: { border: 'var(--rechazo)', color: 'var(--rechazo-deep)' },
    neutral: { border: 'var(--ink-soft)', color: 'var(--ink-soft)' },
  }[tone];
  const sz = { lg: 1, md: 0.72, sm: 0.56 }[size] || 1;
  return (
    <div className="stamp" style={{ transform: `rotate(${rotate}deg) scale(${sz})`, ...style }}>
      <div className="stamp-inner" style={{ borderColor: palette.border, color: palette.color }}>
        <div className="stamp-label">{label}</div>
        {sublabel && <div className="stamp-sub">{sublabel}</div>}
      </div>
    </div>
  );
}

/* ---------- Pill ---------- */
function Pill({ children, tone = 'ink', size = 'md', style, onClick }) {
  const tones = {
    ink:     { bg: 'rgba(26,31,20,0.08)',  fg: 'var(--ink)' },
    olive:   { bg: 'rgba(79,93,60,0.22)',  fg: 'var(--olive)' },
    plaza:   { bg: 'rgba(77,107,52,0.20)', fg: 'var(--plaza-deep)' },
    reserva: { bg: 'rgba(182,128,46,0.22)', fg: 'var(--reserva-deep)' },
    rechazo: { bg: 'rgba(168,58,44,0.18)', fg: 'var(--rechazo-deep)' },
    paper:   { bg: 'var(--paper-2)',        fg: 'var(--ink)' },
    dark:    { bg: 'var(--ink)',            fg: 'var(--paper)' },
  }[tone];
  const sizes = { sm: '10px', md: '11px', lg: '13px' };
  return (
    <span
      className="pill"
      onClick={onClick}
      style={{
        background: tones.bg,
        color: tones.fg,
        fontSize: sizes[size],
        cursor: onClick ? 'pointer' : 'default',
        ...style,
      }}
    >
      {children}
    </span>
  );
}

/* ---------- Stat ---------- */
function Stat({ label, value, hint, mono = false, size = 'md', children }) {
  return (
    <div className="stat">
      <div className="stat-label">{label}</div>
      <div
        className={classNames('stat-value', mono && 'mono')}
        style={{ fontSize: size === 'lg' ? '28px' : size === 'sm' ? '15px' : '20px' }}
      >
        {children ?? value}
      </div>
      {hint && <div className="stat-hint">{hint}</div>}
    </div>
  );
}

/* ---------- Rule ---------- */
function Rule({ label, style }) {
  return (
    <div className="rule" style={style}>
      <span />
      {label && <em>{label}</em>}
      <span />
    </div>
  );
}

/* ---------- Banner ---------- */
function Banner({ children, tone = 'info', icon }) {
  const palette = {
    info:    { bg: 'rgba(26,31,20,0.06)', fg: 'var(--ink)', bd: 'var(--ink-soft)' },
    warn:    { bg: 'rgba(182,128,46,0.12)', fg: 'var(--reserva-deep)', bd: 'var(--reserva)' },
    success: { bg: 'rgba(77,107,52,0.12)', fg: 'var(--plaza-deep)', bd: 'var(--plaza)' },
    error:   { bg: 'rgba(168,58,44,0.12)', fg: 'var(--rechazo-deep)', bd: 'var(--rechazo)' },
  }[tone];
  return (
    <div className="banner" style={{ background: palette.bg, color: palette.fg, borderColor: palette.bd }}>
      {icon && <span className="banner-icon">{icon}</span>}
      <div>{children}</div>
    </div>
  );
}

/* ---------- Icons ---------- */
const ico = (paths, viewBox = '0 0 24 24') => ({ size = 18, color = 'currentColor', style }) => (
  <svg
    width={size} height={size} viewBox={viewBox} fill="none" stroke={color}
    strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" style={style}
  >{paths}</svg>
);
const IconChevron = ico(<polyline points="9 6 15 12 9 18" />);
const IconCheck   = ico(<polyline points="4 13 9 18 20 6" />);
const IconCross   = ico(<><line x1="6" y1="6" x2="18" y2="18" /><line x1="18" y1="6" x2="6" y2="18" /></>);
const IconCircle  = ico(<circle cx="12" cy="12" r="9" />);
const IconWarn    = ico(<><path d="M12 3 2 21h20L12 3z"/><line x1="12" y1="10" x2="12" y2="15"/><circle cx="12" cy="18" r="0.6" fill="currentColor"/></>);
const IconShare   = ico(<><circle cx="18" cy="5" r="2.5"/><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="19" r="2.5"/><line x1="8" y1="11" x2="16" y2="6"/><line x1="8" y1="13" x2="16" y2="18"/></>);
const IconBell    = ico(<><path d="M6 16V11a6 6 0 1 1 12 0v5l1.5 2H4.5L6 16z"/><path d="M10 20a2 2 0 0 0 4 0"/></>);
const IconCopy    = ico(<><rect x="8" y="4" width="12" height="14" rx="1.5"/><path d="M4 8v10a2 2 0 0 0 2 2h10"/></>);
const IconSearch  = ico(<><circle cx="11" cy="11" r="6"/><line x1="20" y1="20" x2="15.5" y2="15.5"/></>);

/* ---------- Toasts ---------- */
const ToastCtx = createContext(null);
function ToastProvider({ children }) {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((msg, tone = 'info') => {
    const id = Math.random().toString(36).slice(2);
    setToasts(t => [...t, { id, msg, tone }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 3200);
  }, []);
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div className="toasts">
        {toasts.map(t => (<div key={t.id} className={`toast toast-${t.tone}`}>{t.msg}</div>))}
      </div>
    </ToastCtx.Provider>
  );
}
function useToast() { return useContext(ToastCtx); }

/* ---------- Export ---------- */
Object.assign(window, {
  classNames, normalizeNIO, isValidNIO,
  Paper, Stamp, Pill, Stat, Rule, Banner,
  IconChevron, IconCheck, IconCross, IconCircle, IconWarn, IconShare, IconBell, IconCopy, IconSearch,
  ToastProvider, useToast,
});
