// Shared UI components, icons, and helpers for BadMatch
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---------- Icons (SF Symbols-inspired, stroke) ---------- */
function Icon({ name, size = 18, stroke = 1.6 }) {
  const s = size;
  const paths = {
    home: <><path d="M3 11l9-7 9 7v9a2 2 0 0 1-2 2h-4v-6h-6v6H5a2 2 0 0 1-2-2v-9z" /></>,
    group: <><circle cx="9" cy="9" r="3.2" /><circle cx="17" cy="11" r="2.5" /><path d="M3 19c0-3 2.7-5 6-5s6 2 6 5" /><path d="M14.5 17.5c.5-2 2.2-3.5 4.5-3.5 1.6 0 3 .7 3 2" /></>,
    user: <><circle cx="12" cy="8" r="3.5" /><path d="M5 20c0-3.5 3.1-6 7-6s7 2.5 7 6" /></>,
    bar: <><path d="M4 20V10M10 20V4M16 20v-7M22 20H2" /></>,
    grid: <><rect x="3.5" y="3.5" width="7" height="7" rx="1.5" /><rect x="13.5" y="3.5" width="7" height="7" rx="1.5" /><rect x="3.5" y="13.5" width="7" height="7" rx="1.5" /><rect x="13.5" y="13.5" width="7" height="7" rx="1.5" /></>,
    shield: <><path d="M12 3l8 3v6c0 5-3.5 8.5-8 9-4.5-.5-8-4-8-9V6l8-3z" /></>,
    plus: <><path d="M12 5v14M5 12h14" /></>,
    minus: <><path d="M5 12h14" /></>,
    check: <><path d="M5 12l4 4 10-10" /></>,
    x: <><path d="M6 6l12 12M18 6L6 18" /></>,
    chevR: <><path d="M9 6l6 6-6 6" /></>,
    chevL: <><path d="M15 6l-6 6 6 6" /></>,
    chevD: <><path d="M6 9l6 6 6-6" /></>,
    edit: <><path d="M4 20h4l10-10-4-4L4 16v4z" /><path d="M14 6l4 4" /></>,
    trash: <><path d="M4 7h16M9 7V4h6v3M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v7M14 11v7" /></>,
    search: <><circle cx="11" cy="11" r="7" /><path d="M21 21l-4.3-4.3" /></>,
    refresh: <><path d="M3 12a9 9 0 0 1 16-5.5L21 4M21 4v5h-5" /><path d="M21 12a9 9 0 0 1-16 5.5L3 20M3 20v-5h5" /></>,
    shuttle: <><path d="M12 3l3 5-3 3-3-3 3-5z" /><path d="M12 11l8 8-3 3-5-3-5 3-3-3 8-8z" /></>,
    play: <><path d="M7 4l13 8-13 8V4z" /></>,
    log: <><rect x="4" y="4" width="16" height="16" rx="2" /><path d="M8 9h8M8 13h8M8 17h5" /></>,
    door: <><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M16 17l5-5-5-5M21 12H9" /></>,
    settings: <><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 0 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 0 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 0 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 0 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z" /></>,
    trophy: <><path d="M8 4h8v4a4 4 0 0 1-8 0V4z" /><path d="M16 6h3v2a3 3 0 0 1-3 3M8 6H5v2a3 3 0 0 0 3 3M10 14h4l-1 4h-2l-1-4zM8 20h8" /></>,
    history: <><path d="M3 12a9 9 0 1 0 3-6.7L3 8M3 3v5h5" /><path d="M12 7v5l3 2" /></>,
    eye: <><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z" /><circle cx="12" cy="12" r="3" /></>,
    help: <><circle cx="12" cy="12" r="9" /><path d="M10 9a2 2 0 1 1 2.5 1.9c-.8.3-1.2.9-1.2 1.6v.5" /><circle cx="12" cy="16.5" r=".5" fill="currentColor" /></>,
    chevron: <><path d="M6 9l6 6 6-6" /></>,
    lock: <><rect x="5" y="11" width="14" height="10" rx="2" /><path d="M8 11V7a4 4 0 0 1 8 0v4" /></>,
    sun: <><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.4 1.4M17.6 17.6L19 19M19 5l-1.4 1.4M6.4 17.6L5 19" /></>,
    moon: <><path d="M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8z" /></>,
    download: <><path d="M12 3v13M7 11l5 5 5-5" /><path d="M4 20h16" /></>
  };
  return (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none"
         stroke="currentColor" strokeWidth={stroke}
         strokeLinecap="round" strokeLinejoin="round">
      {paths[name] || null}
    </svg>
  );
}

/* ---------- Toast ---------- */
const ToastContext = React.createContext(null);
function ToastHost({ children }) {
  const [msg, setMsg] = useState(null);
  const timer = useRef(null);
  const show = useCallback((m) => {
    setMsg(m);
    clearTimeout(timer.current);
    timer.current = setTimeout(() => setMsg(null), 2200);
  }, []);
  return (
    <ToastContext.Provider value={show}>
      {children}
      {msg && <div className="toast">{msg}</div>}
    </ToastContext.Provider>
  );
}
function useToast() { return React.useContext(ToastContext); }

/* ---------- Modal ---------- */
function Modal({ open, onClose, title, children, footer, size }) {
  if (!open) return null;
  return (
    <div className="modal-back" onMouseDown={(e) => e.target === e.currentTarget && onClose && onClose()}>
      <div className={`modal ${size === "large" ? "large" : ""}`}>
        <div className="modal-head">
          <div className="modal-title">{title}</div>
          <button className="btn icon" onClick={onClose}><Icon name="x" size={16} /></button>
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>
  );
}

/* ---------- Segmented control ---------- */
function Segmented({ value, options, onChange }) {
  return (
    <div className="segmented">
      {options.map((o) => (
        <button key={o.value} className={value === o.value ? "active" : ""} onClick={() => onChange(o.value)}>
          {o.label}
        </button>
      ))}
    </div>
  );
}

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

/* ---------- LevelPill ---------- */
function LevelPill({ level, cfg }) {
  if (level == null) return null;
  const bucket = Math.max(1, Math.min(10, Math.floor(level)));
  const display = (typeof formatLevel === "function") ? formatLevel(level, cfg) : Number(level).toFixed(1);
  return <span className="level-pill" data-lv={bucket}>Lv {display}</span>;
}

/* ---------- Brand / authorship credit ----------
   Single source of truth for the "powered by" attribution. Embedded across the
   app (login, sidebar, change-password) to deter rebranding / impersonation. */
const APP_AUTHOR = "GuizBiiGzt";
const APP_YEAR = "2026";
const APP_CREDIT = `Powered by ${APP_AUTHOR} · © ${APP_YEAR}`;

// Compact one-line credit. variant: "muted" (default) | "footer" | "inline"
function BrandCredit({ variant = "muted", style }) {
  const base = {
    muted:  { fontSize: 12, color: "var(--text-3)", letterSpacing: "0.02em" },
    footer: { fontSize: 11.5, color: "var(--text-3)", letterSpacing: "0.03em", opacity: 0.9 },
    inline: { fontSize: 10, color: "var(--text-3)", letterSpacing: "0.02em" },
  }[variant] || {};
  return (
    <span className="brand-credit" style={{ ...base, ...style }}>
      Powered by <b style={{ color: "var(--text-2)", fontWeight: 600 }}>{APP_AUTHOR}</b>
      <span style={{ opacity: 0.7 }}> · © {APP_YEAR}</span>
    </span>
  );
}

/* ---------- Role helpers ---------- */
const ROLE_LABELS = {
  super: "Super User",
  admin: "Group Owner",   // renamed from "User Admin"
  viewer: "Viewer",       // legacy
};
function roleLabel(role) { return ROLE_LABELS[role] || role; }

/* ---------- Gender helpers ---------- */
const GENDER_LABELS = { M: "ชาย", F: "หญิง", U: "ไม่ระบุ" };
function genderLabel(g) { return GENDER_LABELS[g] || GENDER_LABELS.U; }
const GENDER_MODE_LABELS = {
  any:    "ไม่สนเพศ",
  male:   "ชายล้วน",
  female: "หญิงล้วน",
  mixed:  "คู่ผสม (ชาย+หญิง)",
};
function genderModeLabel(m) { return GENDER_MODE_LABELS[m] || GENDER_MODE_LABELS.any; }

/* ---------- Tooltip ----------
   Hover on desktop, tap-to-open on mobile.
   Usage: <InfoTip text="explanation">label</InfoTip>
   or: <InfoTip text="..." /> for just the icon
*/
function InfoTip({ text, children, side = "top", size = 14 }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    if (!open) return;
    const onClick = (e) => { if (!ref.current?.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onClick);
    document.addEventListener("touchstart", onClick);
    return () => {
      document.removeEventListener("mousedown", onClick);
      document.removeEventListener("touchstart", onClick);
    };
  }, [open]);

  return (
    <span className="infotip-wrap" ref={ref}>
      {children}
      <button type="button" className={`infotip-btn ${open ? "open" : ""}`}
              onMouseEnter={() => setOpen(true)}
              onMouseLeave={() => setOpen(false)}
              onClick={(e) => { e.preventDefault(); e.stopPropagation(); setOpen(o => !o); }}
              aria-label="ข้อมูลเพิ่มเติม">
        <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <circle cx="12" cy="12" r="10" />
          <line x1="12" y1="11" x2="12" y2="16" />
          <circle cx="12" cy="8" r="0.6" fill="currentColor" stroke="none" />
        </svg>
      </button>
      {open && (
        <span className={`infotip-pop infotip-${side}`} role="tooltip">
          {text}
        </span>
      )}
    </span>
  );
}

/* ---------- Helpers ---------- */
function initials(name) {
  if (!name) return "?";
  const parts = name.trim().split(/\s+/);
  return (parts[0]?.[0] || "") + (parts[1]?.[0] || "");
}
function fmtTime(d) {
  d = new Date(d);
  const hh = String(d.getHours()).padStart(2, "0");
  const mm = String(d.getMinutes()).padStart(2, "0");
  return `${hh}:${mm}`;
}
function fmtDate(d) {
  d = new Date(d);
  const dd = String(d.getDate()).padStart(2, "0");
  const mo = String(d.getMonth() + 1).padStart(2, "0");
  return `${dd}/${mo}`;
}

/* ---------- PlayerRow (for selectable lists) ---------- */
function PlayerRow({ player, selected, onToggle, right }) {
  return (
    <div className={`list-item selectable ${selected ? "checked" : ""}`} onClick={onToggle}>
      <div className="check-circle">{selected && <Icon name="check" size={14} stroke={2.4} />}</div>
      <div className="grow">
        <div className="name">{player.name}</div>
        <div className="meta">
          {player.hand ? `ถนัด${player.hand === "L" ? "ซ้าย" : "ขวา"}` : "—"}
          {player.age ? ` · ${player.age} ปี` : ""}
          {player.stats ? ` · ${player.stats.wins}W ${player.stats.losses}L` : ""}
        </div>
      </div>
      <LevelPill level={player.level} />
      {right}
    </div>
  );
}

Object.assign(window, {
  Icon, ToastHost, useToast, Modal, Segmented, Toggle, LevelPill, PlayerRow,
  initials, fmtTime, fmtDate,
  InfoTip, roleLabel, ROLE_LABELS,
  genderLabel, genderModeLabel, GENDER_LABELS, GENDER_MODE_LABELS,
  BrandCredit, APP_AUTHOR, APP_YEAR, APP_CREDIT,
});
