/* global React, Ic */
// Shared functional UI atoms for Flux Discounts
const { useState: useS, useEffect: useE, useRef: useR, useCallback } = React;

// ---------- toast system ----------
let _toastId = 0;
const _toastSubs = new Set();
function toast(message, type = "info") {
  const t = { id: ++_toastId, message, type };
  _toastSubs.forEach((f) => f(t));
}
function ToastHost() {
  const [items, setItems] = useS([]);
  useE(() => {
    const f = (t) => {
      setItems((xs) => [...xs, t]);
      setTimeout(() => setItems((xs) => xs.filter((x) => x.id !== t.id)), 3000);
    };
    _toastSubs.add(f);
    return () => _toastSubs.delete(f);
  }, []);
  const icon = { success: Ic.check, error: Ic.x, info: Ic.zap };
  return (
    <div className="toast-host">
      {items.map((t) => {
        const I = icon[t.type] || Ic.zap;
        return (
          <div key={t.id} className={`toast ${t.type}`}>
            <I className="ic" />
            <span>{t.message}</span>
          </div>
        );
      })}
    </div>
  );
}

// ---------- copy button ----------
function Copyable({ text, label, className = "btn ghost sm", iconOnly = false }) {
  const [done, setDone] = useS(false);
  const copy = (e) => {
    e.stopPropagation();
    const write = navigator.clipboard
      ? navigator.clipboard.writeText(text)
      : Promise.reject();
    write.catch(() => {
      const ta = document.createElement("textarea");
      ta.value = text; document.body.appendChild(ta); ta.select();
      try { document.execCommand("copy"); } catch {}
      ta.remove();
    }).finally(() => {});
    // optimistic
    setDone(true); setTimeout(() => setDone(false), 1400);
    toast("Copied to clipboard", "success");
  };
  const I = done ? Ic.check : Ic.copy;
  return (
    <button className={className} onClick={copy} title="Copy">
      <I className="ico" style={{ width: 13, height: 13 }} />
      {!iconOnly && (label || (done ? "Copied" : "Copy"))}
    </button>
  );
}

// ---------- code block with syntax-ish highlight + copy ----------
function CodeBlock({ code, copyText }) {
  return (
    <div className="code-wrap">
      <div className="copy-fab"><Copyable text={copyText != null ? copyText : code} iconOnly className="btn sm" /></div>
      <pre className="code">{code}</pre>
    </div>
  );
}

// ---------- field ----------
function Field({ label, hint, children, style }) {
  return (
    <div className="field" style={style}>
      {label && <label className="field-label">{label}{hint && <span className="muted" style={{ fontWeight: 400 }}> · {hint}</span>}</label>}
      {children}
    </div>
  );
}

// ---------- modal ----------
function Modal({ title, icon, onClose, children, footer, size }) {
  useE(() => {
    const k = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", k);
    return () => document.removeEventListener("keydown", k);
  }, [onClose]);
  const I = icon;
  // Portal to <body> so the fixed scrim is positioned against the real viewport,
  // not a transformed ancestor (.fade-in views create a containing block).
  return ReactDOM.createPortal(
    <div className="modal-scrim" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className={`modal ${size || ""}`} onMouseDown={(e) => e.stopPropagation()}>
        <div className="modal-head">
          {I && <I style={{ width: 17, height: 17, color: "var(--indigo)" }} />}
          <h3>{title}</h3>
          <button className="btn ghost icon x" onClick={onClose}><Ic.x style={{ width: 15, height: 15 }} /></button>
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>,
    document.body
  );
}

// ---------- toggle ----------
function Switch({ on, onChange }) {
  return <div className={`switch ${on ? "on" : ""}`} onClick={(e) => { e.stopPropagation(); onChange(!on); }} role="switch" aria-checked={on} />;
}

// ---------- segmented ----------
function Seg({ value, onChange, options }) {
  return (
    <div className="seg">
      {options.map((o) => (
        <button key={o.value} className={value === o.value ? "on" : ""} onClick={() => onChange(o.value)}>
          {o.icon ? React.createElement(o.icon, { style: { width: 13, height: 13 } }) : null}
          {o.label}
        </button>
      ))}
    </div>
  );
}

// ---------- discount thumbnail (image or striped placeholder) ----------
function DiscountThumb({ d, className }) {
  if (d.image) return <img src={d.image} alt="" className={className} onError={(e) => { e.currentTarget.style.display = "none"; }} />;
  return <div className={`thumb ${className || ""}`}>product shot</div>;
}

// ---------- status pill for delivery ----------
function DeliveryPill({ status, code }) {
  if (status === "delivered") return <span className="pill green dot">DELIVERED{code ? ` · ${code}` : ""}</span>;
  if (status === "failed") return <span className="pill red dot">FAILED{code ? ` · ${code}` : ""}</span>;
  if (status === "sending") return <span className="pill yellow dot">SENDING</span>;
  return <span className="pill">{status}</span>;
}

// ---------- confirm helper (inline two-step button) ----------
function DangerButton({ onConfirm, children, confirmLabel = "Confirm?", className = "btn danger sm" }) {
  const [armed, setArmed] = useS(false);
  useE(() => { if (!armed) return; const t = setTimeout(() => setArmed(false), 2600); return () => clearTimeout(t); }, [armed]);
  return (
    <button className={className} onClick={(e) => { e.stopPropagation(); if (armed) { onConfirm(); setArmed(false); } else setArmed(true); }}>
      {armed ? confirmLabel : children}
    </button>
  );
}

Object.assign(window, {
  toast, ToastHost, Copyable, CodeBlock, Field, Modal, Switch, Seg, DiscountThumb, DeliveryPill, DangerButton,
});
