// extras.jsx — additional components: Skeleton, Spinner, Separator, Toggle, HoverCard,
// InputOTP, Stepper, EmptyState, Sheet, CommandPalette, Combobox, ContextMenu
const { useState: useStateX, useRef: useRefX, useEffect: useEffectX } = React;

/* ---------- Skeleton ---------- */
function Skeleton({ w, h, circle, className = "", style }) {
  return <div className={"skeleton " + (circle ? "skeleton-circle " : "") + className} style={{ width: w, height: h, ...style }} />;
}

/* ---------- Spinner ---------- */
function Spinner({ size, style, className = "" }) { return <span className={"spinner" + (size ? " " + size : "") + (className ? " " + className : "")} style={style} role="status" aria-label="carregando" />; }

/* ---------- Separator ---------- */
function Separator({ vertical, label }) {
  if (label) return <div className="separator-label">{label}</div>;
  return <div className={"separator" + (vertical ? " vertical" : "")} role="separator" />;
}

/* ---------- Toggle ---------- */
function Toggle({ pressed, onChange, icon, children }) {
  return (
    <button className="toggle" data-on={!!pressed} aria-pressed={!!pressed} onClick={() => onChange && onChange(!pressed)}>
      {icon && <Icon name={icon} />}{children}
    </button>
  );
}
function ToggleGroup({ options, value, onChange, multi }) {
  const isOn = (v) => multi ? (value || []).includes(v) : value === v;
  const toggle = (v) => {
    if (multi) { const cur = value || []; onChange(cur.includes(v) ? cur.filter((x) => x !== v) : [...cur, v]); }
    else onChange(v);
  };
  return (
    <div className="toggle-group">
      {options.map((o) => (
        <button key={o.value} className="toggle" data-on={isOn(o.value)} onClick={() => toggle(o.value)}>
          {o.icon && <Icon name={o.icon} />}{o.label}
        </button>
      ))}
    </div>
  );
}

/* ---------- HoverCard ---------- */
function HoverCard({ trigger, children, width = 280 }) {
  return <span className="hovercard-wrap">{trigger}<span className="hovercard" style={{ width }}>{children}</span></span>;
}

/* ---------- Input OTP ---------- */
function InputOTP({ length = 6, value = "", onChange, groupAt }) {
  const refs = useRefX([]);
  const set = (i, ch) => {
    const v = value.split("");
    v[i] = ch.slice(-1);
    const next = v.join("").slice(0, length);
    onChange && onChange(next);
    if (ch && i < length - 1) refs.current[i + 1] && refs.current[i + 1].focus();
  };
  const onKey = (i, e) => {
    if (e.key === "Backspace" && !value[i] && i > 0) refs.current[i - 1] && refs.current[i - 1].focus();
  };
  const cells = [];
  for (let i = 0; i < length; i++) {
    cells.push(
      <input key={i} ref={(el) => (refs.current[i] = el)} className={"otp-cell" + (value[i] ? " filled" : "")}
        inputMode="numeric" maxLength={1} value={value[i] || ""} onChange={(e) => set(i, e.target.value)} onKeyDown={(e) => onKey(i, e)} />
    );
    if (groupAt && (i + 1) % groupAt === 0 && i < length - 1) cells.push(<span key={"s" + i} className="otp-sep">–</span>);
  }
  return <div className="otp">{cells}</div>;
}

/* ---------- Stepper ---------- */
function Stepper({ steps, current = 0 }) {
  return (
    <div className="stepper">
      {steps.map((s, i) => {
        const state = i < current ? "done" : i === current ? "active" : "pending";
        return (
          <div key={i} className={"step " + state}>
            <div className="step-dot">{i < current ? <Icon name="check" /> : i + 1}</div>
            <div className="step-label">{s.label}</div>
            {s.sub && <div className="step-sub">{s.sub}</div>}
          </div>
        );
      })}
    </div>
  );
}

/* ---------- EmptyState ---------- */
function EmptyState({ icon = "search", title, desc, action }) {
  return (
    <div className="empty">
      <Icon name={icon} />
      <h3>{title}</h3>
      {desc && <p style={{ maxWidth: 360, margin: "0 auto" }}>{desc}</p>}
      {action && <div style={{ marginTop: 18 }}>{action}</div>}
    </div>
  );
}

/* ---------- Sheet / Drawer ---------- */
function Sheet({ open, onClose, title, desc, children, footer, side }) {
  useEffectX(() => {
    if (!open) return;
    const h = (e) => e.key === "Escape" && onClose();
    document.addEventListener("keydown", h);
    return () => document.removeEventListener("keydown", h);
  }, [open, onClose]);
  if (!open) return null;
  const align = side === "left" ? "flex-start" : side === "bottom" ? "center" : "flex-end";
  return (
    <div className="overlay" style={{ padding: 0, justifyContent: align, alignItems: side === "bottom" ? "flex-end" : "stretch" }} onMouseDown={(e) => e.target === e.currentTarget && onClose()}>
      <div className={"sheet" + (side === "left" ? " left" : side === "bottom" ? " bottom" : "")}>
        <div className="sheet-header">
          <div><div className="sheet-title">{title}</div>{desc && <div className="sheet-desc">{desc}</div>}</div>
          <Button variant="ghost" size="sm" icon="x" onClick={onClose} />
        </div>
        <div className="sheet-body">{children}</div>
        {footer && <div className="sheet-footer">{footer}</div>}
      </div>
    </div>
  );
}

/* ---------- Command Palette ---------- */
function CommandPalette({ open, onClose, groups }) {
  const [q, setQ] = useStateX("");
  const [active, setActive] = useStateX(0);
  const inputRef = useRefX(null);
  const flat = [];
  const filtered = groups.map((g) => ({
    ...g, items: g.items.filter((it) => it.label.toLowerCase().includes(q.toLowerCase())),
  })).filter((g) => g.items.length);
  filtered.forEach((g) => g.items.forEach((it) => flat.push(it)));

  useEffectX(() => { if (open) { setQ(""); setActive(0); setTimeout(() => inputRef.current && inputRef.current.focus(), 30); } }, [open]);
  useEffectX(() => {
    if (!open) return;
    const h = (e) => {
      if (e.key === "Escape") onClose();
      else if (e.key === "ArrowDown") { e.preventDefault(); setActive((a) => Math.min(a + 1, flat.length - 1)); }
      else if (e.key === "ArrowUp") { e.preventDefault(); setActive((a) => Math.max(a - 1, 0)); }
      else if (e.key === "Enter") { e.preventDefault(); const it = flat[active]; if (it) { it.onSelect && it.onSelect(); onClose(); } }
    };
    document.addEventListener("keydown", h);
    return () => document.removeEventListener("keydown", h);
  }, [open, active, flat.length]);
  if (!open) return null;
  let idx = -1;
  return (
    <div className="command-overlay" onMouseDown={(e) => e.target === e.currentTarget && onClose()}>
      <div className="command" role="dialog" aria-modal="true">
        <div className="command-search">
          <Icon name="search" />
          <input ref={inputRef} value={q} onChange={(e) => { setQ(e.target.value); setActive(0); }} placeholder="Buscar comandos, soluções, páginas..." />
          <kbd>ESC</kbd>
        </div>
        <div className="command-list">
          {flat.length === 0 && <div className="command-empty">Nenhum resultado para "{q}".</div>}
          {filtered.map((g) => (
            <div key={g.label}>
              <div className="command-group-label">{g.label}</div>
              {g.items.map((it) => {
                idx++; const myIdx = idx;
                return (
                  <div key={it.label} className="command-item" data-active={myIdx === active}
                    onMouseEnter={() => setActive(myIdx)} onClick={() => { it.onSelect && it.onSelect(); onClose(); }}>
                    <Icon name={it.icon || "arrowRight"} /><span>{it.label}</span>
                    {it.shortcut && <span className="shortcut">{it.shortcut}</span>}
                  </div>
                );
              })}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ---------- Combobox ---------- */
function Combobox({ options, value, onChange, placeholder = "Selecione..." }) {
  const [open, setOpen] = useStateX(false);
  const [q, setQ] = useStateX("");
  const ref = useRefX(null);
  useOutside(ref, () => setOpen(false));
  const sel = options.find((o) => o.value === value);
  const filtered = options.filter((o) => o.label.toLowerCase().includes(q.toLowerCase()));
  return (
    <div className="select" data-open={open} ref={ref} style={{ minWidth: 240 }}>
      <button type="button" className="select-trigger" onClick={() => { setOpen((o) => !o); setQ(""); }}>
        <span className={sel ? "" : "placeholder"}>{sel ? sel.label : placeholder}</span>
        <Icon name="chevrons-up-down" />
      </button>
      {open && (
        <div className="combobox-menu">
          <div className="combobox-search">
            <Icon name="search" />
            <input autoFocus value={q} onChange={(e) => setQ(e.target.value)} placeholder="Buscar..." />
          </div>
          <div className="combobox-list">
            {filtered.length === 0 && <div className="command-empty" style={{ padding: 20 }}>Nada encontrado.</div>}
            {filtered.map((o) => (
              <div key={o.value} className="select-item" data-selected={o.value === value}
                onClick={() => { onChange && onChange(o.value); setOpen(false); }}>
                <span>{o.label}</span>{o.value === value && <Icon name="check" />}
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

/* ---------- Context Menu ---------- */
function ContextMenu({ items, children }) {
  const [pos, setPos] = useStateX(null);
  useEffectX(() => {
    if (!pos) return;
    const close = () => setPos(null);
    document.addEventListener("click", close);
    document.addEventListener("scroll", close, true);
    return () => { document.removeEventListener("click", close); document.removeEventListener("scroll", close, true); };
  }, [pos]);
  const onCtx = (e) => { e.preventDefault(); setPos({ x: e.clientX, y: e.clientY }); };
  return (
    <>
      <div onContextMenu={onCtx}>{children}</div>
      {pos && (
        <div className="menu" style={{ position: "fixed", top: pos.y, left: pos.x, zIndex: 130 }}>
          {items.map((it, i) => it.sep ? <div key={i} className="menu-sep" /> : (
            <div key={i} className={"menu-item" + (it.danger ? " danger" : "")} onClick={() => { it.onClick && it.onClick(); setPos(null); }}>
              {it.icon && <Icon name={it.icon} />}<span>{it.label}</span>{it.shortcut && <span className="shortcut">{it.shortcut}</span>}
            </div>
          ))}
        </div>
      )}
    </>
  );
}

Object.assign(window, { Skeleton, Spinner, Separator, Toggle, ToggleGroup, HoverCard, InputOTP, Stepper, EmptyState, Sheet, CommandPalette, Combobox, ContextMenu });
