

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

const CodesContext = createContext({ codes: [], colorForCode: () => CODE_PALETTE[CODE_PALETTE.length - 1] });
function useColorForCode() {return useContext(CodesContext).colorForCode;}

function MapCode({ code, size = "md", onClick, dim }) {
  const colorForCode = useColorForCode();
  if (!code) return null;
  const c = colorForCode(code);
  return (
    <span className="code code-brackets" style={{
      color: dim ? 'var(--ink-4)' : c.text,
      background: dim ? 'transparent' : c.bg,
      borderColor: dim ? 'var(--line)' : c.border,
      cursor: onClick ? 'pointer' : 'default',
      fontSize: size === 'lg' ? 14 : size === 'sm' ? 12 : 13, borderStyle: "dashed"
    }} onClick={onClick}>
      {code}
    </span>);

}

function StatusPill({ status }) {
  const s = STATUSES[status] || STATUSES.idle;
  const color = { ok: 'var(--ok)', info: 'var(--ink-3)', warn: 'var(--warn)', bad: 'var(--bad)', mute: 'var(--ink-4)' }[s.dot];
  return (
    <span className="status-pill">
      <span className={"sym" + (status === "running" ? " pulse-soft" : "")} style={{ color }}>{s.sym}</span>
      {s.label}
    </span>);

}

function Checkbox({ checked, indeterminate, onClick, size = 17, hit = 9 }) {
  return (
    <span
      role="checkbox"
      aria-checked={indeterminate ? "mixed" : !!checked}
      onClick={(e) => {e.stopPropagation();onClick?.(e);}}
      className="check-hit"
      style={{ padding: hit, margin: -hit }}>
      <span style={{
        width: size, height: size, borderRadius: 4,
        border: '1.5px solid ' + (checked || indeterminate ? 'var(--accent)' : 'var(--line-strong)'),
        background: checked || indeterminate ? 'var(--accent)' : 'transparent',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        transition: 'background var(--t) var(--ease), border-color var(--t) var(--ease)',
        color: '#fff'
      }}>
        {checked && <I.Check size={12} strokeWidth={3.5} />}
        {!checked && indeterminate && <I.Minus size={12} strokeWidth={3.5} />}
      </span>
    </span>);

}

function Popover({ open, onClose, anchorRef, children, align = "right", offset = 6, width = 240 }) {
  const ref = useRef(null);
  const [pos, setPos] = useState(null);
  useEffect(() => {
    if (!open) return;
    const calc = () => {
      const a = anchorRef.current?.getBoundingClientRect();
      if (!a) return;
      let left = align === "right" ? a.right - width : a.left;
      
      const margin = 8;
      const maxLeft = window.innerWidth - width - margin;
      if (left > maxLeft) left = maxLeft;
      if (left < margin) left = margin;
      let top = a.bottom + offset;
      
      const estH = 320;
      if (top + estH > window.innerHeight - margin && a.top > estH + margin) {
        top = a.top - estH - offset;
      }
      setPos({ top, left });
    };
    calc();
    const onDoc = (e) => {if (ref.current && !ref.current.contains(e.target) && !anchorRef.current?.contains(e.target)) onClose();};
    const onKey = (e) => {if (e.key === 'Escape') onClose();};
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    window.addEventListener('resize', calc);
    window.addEventListener('scroll', calc, true);
    return () => {document.removeEventListener('mousedown', onDoc);document.removeEventListener('keydown', onKey);window.removeEventListener('resize', calc);window.removeEventListener('scroll', calc, true);};
  }, [open, onClose, anchorRef, align, offset, width]);
  if (!open || !pos) return null;
  return (
    <div ref={ref} className="anim-pop" style={{
      position: 'fixed', top: pos.top, left: pos.left, width,
      background: 'var(--card-hi)', border: '1px solid var(--line-soft)', borderRadius: 8,
      boxShadow: '0 12px 40px rgba(0,0,0,.6)', padding: 5, zIndex: 200,
      transformOrigin: align === "right" ? "top right" : "top left"
    }}>
      {children}
    </div>);

}

function MenuItem({ icon: IconCmp, label, danger, onClick, mono }) {
  return (
    <div onClick={onClick} className="menu-item" style={{
      display: 'flex', alignItems: 'center', gap: 10, padding: '8px 11px', borderRadius: 5, cursor: 'pointer',
      color: danger ? 'var(--bad)' : 'var(--ink-2)',
      fontSize: 13.5, fontFamily: mono ? "IBM Plex Mono, SF Mono, Menlo, monospace" : 'inherit'
    }}
    onMouseEnter={(e) => {e.currentTarget.style.background = 'var(--panel-2)';e.currentTarget.style.color = danger ? 'var(--bad)' : 'var(--ink)';}}
    onMouseLeave={(e) => {e.currentTarget.style.background = 'transparent';e.currentTarget.style.color = danger ? 'var(--bad)' : 'var(--ink-2)';}}>
      {IconCmp && <IconCmp size={14} />}
      <span style={{ flex: 1 }}>{label}</span>
    </div>);

}

function SearchInput({ value, onChange, placeholder, width = 300 }) {
  return (
    <div className="input" style={{ width, padding: '7px 12px' }}>
      <I.Search size={15} color="var(--ink-3)" />
      <input value={value} onChange={(e) => onChange(e.target.value)} placeholder={placeholder || "Search…"} />
      {value &&
      <button className="icon-btn" onClick={() => onChange("")} style={{ width: 24, height: 24 }}>
          <I.X size={14} />
        </button>
      }
    </div>);

}

function SingleCodePicker({ open, onClose, anchorRef, value, onChange, codes, align = "left" }) {
  const [query, setQuery] = useState("");
  const colorForCode = useColorForCode();
  useEffect(() => {if (open) setQuery("");}, [open]);
  const filtered = codes.filter((c) => !query || c.toLowerCase().includes(query.toLowerCase()));
  return (
    <Popover open={open} onClose={onClose} anchorRef={anchorRef} align={align} width={300}>
      <div style={{ padding: 5 }}>
        <div className="input" style={{ padding: '6px 10px', marginBottom: 6 }}>
          <I.Search size={13} color="var(--ink-4)" />
          <input className="mono" placeholder="filter codes…" value={query} onChange={(e) => setQuery(e.target.value)} style={{ fontSize: 13 }} autoFocus />
        </div>
        <div style={{ maxHeight: 280, overflow: 'auto', padding: 2 }}>
          {filtered.map((c) => {
            const on = c === value;
            const col = colorForCode(c);
            return (
              <div key={c} className="menu-item" onClick={() => {onChange(c);onClose();}} style={{
                display: 'flex', alignItems: 'center', gap: 10, padding: '8px 9px', borderRadius: 5, cursor: 'pointer',
                background: on ? 'var(--panel-2)' : 'transparent'
              }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'var(--panel-2)'}
              onMouseLeave={(e) => {if (!on) e.currentTarget.style.background = 'transparent';}}>
                <span style={{ width: 10, height: 10, borderRadius: 3, background: col.dot }}></span>
                <span className="mono" style={{ fontSize: 13, color: on ? 'var(--ink)' : 'var(--ink-2)' }}>{c}</span>
                {on && <I.Check size={13} style={{ marginLeft: 'auto', color: 'var(--accent)' }} />}
              </div>);

          })}
          {filtered.length === 0 && <div className="mono" style={{ padding: 12, fontSize: 13, color: 'var(--ink-5)' }}>// no matches</div>}
        </div>
      </div>
    </Popover>);

}

// Confirm modal — for resource-heavy bulk actions
function ConfirmModal({ open, onClose, onConfirm, title, message, confirmLabel = "Confirm", danger, summary }) {
  if (!open) return null;
  return (
    <>
      <div className="scrim" onClick={onClose}></div>
      <div className="anim-modal" style={{
        position: 'fixed', left: '50%', top: '50%', transform: 'translate(-50%, -50%)',
        width: 460, maxWidth: '92vw',
        background: 'var(--panel)', border: '1px solid var(--line-strong)', borderRadius: 10,
        zIndex: 95, overflow: 'hidden',
        boxShadow: '0 16px 48px rgba(0,0,0,.12)'
      }}>
        <div style={{ padding: '18px 20px 16px', borderBottom: '1px solid var(--line)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
            <span style={{
              width: 32, height: 32, borderRadius: 7,
              background: danger ? 'rgba(224,122,122,.14)' : 'var(--accent-soft)',
              color: danger ? 'var(--bad)' : 'var(--accent)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              flexShrink: 0
            }}>
              <I.AlertTriangle size={16} />
            </span>
            <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>{title}</h3>
          </div>
          <p style={{ margin: '13px 0 0', fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.55 }}>{message}</p>
          {summary &&
          <div className="mono" style={{
            marginTop: 13, padding: '10px 13px', background: 'var(--panel-2)',
            border: '1px solid var(--line)', borderRadius: 6, fontSize: 12.5, color: 'var(--ink-3)'
          }}>{summary}</div>
          }
        </div>
        <div style={{ padding: '13px 20px', background: 'var(--panel-2)', display: 'flex', justifyContent: 'flex-end', gap: 9 }}>
          <button className="btn btn-sm" onClick={onClose}>Cancel</button>
          <button className={"btn btn-sm " + (danger ? "" : "btn-primary")} onClick={() => {onConfirm();onClose();}}
          style={danger ? { background: 'var(--bad)', borderColor: 'var(--bad)', color: '#111', fontWeight: 600 } : null}>
            {confirmLabel}
          </button>
        </div>
      </div>
    </>);

}

Object.assign(window, { CodesContext, useColorForCode, MapCode, StatusPill, Checkbox, Popover, MenuItem, SearchInput, SingleCodePicker, ConfirmModal });