// Accounts & moderation — mock auth, login modal, sidebar account block,
// toast dispatcher, and shared loading/empty/error states.
// All state is mocked; no real Clerk/Turnstile/network calls.

// ── Extra icons (merged into the shared ic map) ─────────────────────────────
const ic2 = {
  user:     <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="8" cy="5.5" r="2.6"/><path d="M3 13.2a5 5 0 0 1 10 0"/></svg>,
  login:    <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M9 2.5h3a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H9M9.5 8H3m0 0 2.5-2.5M3 8l2.5 2.5"/></svg>,
  logout:   <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M7 2.5H4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3M10.5 8H6m4.5 0L8 5.5M10.5 8 8 10.5"/></svg>,
  upload:   <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M8 10.5V3m0 0L5 6m3-3 3 3M3 12.5h10"/></svg>,
  inbox:    <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M2.5 9.5 4 4h8l1.5 5.5M2.5 9.5v2a1 1 0 0 0 1 1h9a1 1 0 0 0 1-1v-2M2.5 9.5H6l.8 1.3h2.4L10 9.5h3.5"/></svg>,
  gear:     <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="8" cy="8" r="2"/><path d="M8 1.8v1.6M8 12.6v1.6M14.2 8h-1.6M3.4 8H1.8M12.4 3.6l-1.1 1.1M4.7 11.3l-1.1 1.1M12.4 12.4l-1.1-1.1M4.7 4.7 3.6 3.6"/></svg>,
  shield:   <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M8 1.8 3 3.6v4.2c0 3 2.1 5 5 6.4 2.9-1.4 5-3.4 5-6.4V3.6L8 1.8z"/><path d="m6 8 1.5 1.5L10.5 6"/></svg>,
  lock:     <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><rect x="3.5" y="7" width="9" height="6.5" rx="1.2"/><path d="M5.5 7V5a2.5 2.5 0 0 1 5 0v2"/></svg>,
  ban:      <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="8" cy="8" r="5.5"/><path d="m4.2 4.2 7.6 7.6"/></svg>,
  mute:     <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M8 3 5 5.5H3v5h2L8 13V3z"/><path d="M11 6.5 14 9.5M14 6.5 11 9.5"/></svg>,
  users:    <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="6" cy="5.5" r="2.2"/><path d="M2.3 12.5a3.7 3.7 0 0 1 7.4 0M10.5 4a2 2 0 0 1 0 3.8M11 12.5a3.7 3.7 0 0 0-1.3-2.8"/></svg>,
  list2:    <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M5.5 4.5h8M5.5 8h8M5.5 11.5h8"/><circle cx="2.7" cy="4.5" r=".9" fill="currentColor"/><circle cx="2.7" cy="8" r=".9" fill="currentColor"/><circle cx="2.7" cy="11.5" r=".9" fill="currentColor"/></svg>,
  gauge:    <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M2.6 11.5a6 6 0 1 1 10.8 0"/><path d="M8 8.5 10.5 6"/><circle cx="8" cy="8.5" r=".9" fill="currentColor"/></svg>,
  trash:    <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M3 4.5h10M6 4.5V3.2a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v1.3M4.5 4.5l.6 8a1 1 0 0 0 1 .9h3.8a1 1 0 0 0 1-.9l.6-8"/></svg>,
  empty:    <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.3"><rect x="2.5" y="3" width="11" height="10" rx="1.5"/><path d="M2.5 9.5H6l.8 1.3h2.4L10 9.5h3.5" strokeWidth="1.3"/></svg>,
  google:   <svg viewBox="0 0 18 18"><path fill="#4285F4" d="M17.6 9.2c0-.6-.05-1.18-.16-1.74H9v3.28h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.9c1.7-1.56 2.66-3.88 2.66-6.52z"/><path fill="#34A853" d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.9-2.26c-.8.54-1.84.86-3.06.86-2.35 0-4.34-1.59-5.05-3.72H.93v2.33A9 9 0 0 0 9 18z"/><path fill="#FBBC05" d="M3.95 10.7a5.4 5.4 0 0 1 0-3.42V4.96H.93a9 9 0 0 0 0 8.07l3.02-2.34z"/><path fill="#EA4335" d="M9 3.58c1.32 0 2.5.46 3.44 1.35l2.58-2.58A8.99 8.99 0 0 0 .93 4.96l3.02 2.33C4.66 5.16 6.65 3.58 9 3.58z"/></svg>,
  discord:  <svg viewBox="0 0 16 16" fill="#5865F2"><path d="M13.2 3.5A11 11 0 0 0 10.5 2.7l-.16.32a9.9 9.9 0 0 1 2.4.78A8.6 8.6 0 0 0 3.3 3.8a9.8 9.8 0 0 1 2.4-.78L5.5 2.7A11 11 0 0 0 2.8 3.5C1.2 5.9.75 8.2.97 10.5a11.1 11.1 0 0 0 3.36 1.7l.43-.72c-.45-.17-.88-.38-1.28-.63l.1-.07a7.9 7.9 0 0 0 6.84 0l.1.07c-.4.25-.83.46-1.28.63l.43.72a11 11 0 0 0 3.36-1.7c.27-2.66-.45-4.94-1.84-7zM5.9 9.1c-.65 0-1.18-.6-1.18-1.34S5.24 6.4 5.9 6.4c.66 0 1.19.6 1.18 1.35C7.08 8.5 6.55 9.1 5.9 9.1zm4.2 0c-.65 0-1.18-.6-1.18-1.34S9.44 6.4 10.1 6.4c.66 0 1.19.6 1.18 1.35 0 .74-.52 1.34-1.18 1.34z"/></svg>,
};

const AVATAR_COLORS = [
  'oklch(0.62 0.16 25)', 'oklch(0.62 0.15 50)', 'oklch(0.60 0.14 145)',
  'oklch(0.58 0.15 200)', 'oklch(0.56 0.16 265)', 'oklch(0.58 0.17 310)',
  'oklch(0.60 0.15 95)', 'oklch(0.58 0.15 170)',
];
const NICK_ADJ = ['Pixel', 'Spike', 'Cherry', 'Quantum', 'Neon', 'Turbo', 'Velvet', 'Cosmic', 'Iron', 'Lunar', 'Static', 'Crimson', 'Echo', 'Frost'];
const NICK_NOUN = ['Drifter', 'Runner', 'Jumper', 'Phantom', 'Voyager', 'Saver', 'Maverick', 'Specter', 'Climber', 'Nomad', 'Glider', 'Warden'];

function genIdentity() {
  const a = NICK_ADJ[Math.floor(Math.random() * NICK_ADJ.length)];
  const n = NICK_NOUN[Math.floor(Math.random() * NICK_NOUN.length)];
  const num = Math.floor(Math.random() * 90) + 10;
  const nick = `${a}${n}${num}`;
  const color = AVATAR_COLORS[Math.floor(Math.random() * AVATAR_COLORS.length)];
  return { nick, color, initial: a[0].toUpperCase() };
}

// Persisted identity so the nickname stays stable across reloads.
function loadIdentity() {
  try {
    const saved = localStorage.getItem('archive_identity');
    if (saved) return JSON.parse(saved);
  } catch (e) {}
  const id = genIdentity();
  try { localStorage.setItem('archive_identity', JSON.stringify(id)); } catch (e) {}
  return id;
}

// ── Avatar ──────────────────────────────────────────────────────────────────
function Avatar({ identity, size = 26, className = '' }) {
  return (
    <span className={'avatar ' + className} style={{ background: identity.color, width: size, height: size, fontSize: size * 0.46 }}>
      {identity.initial}
    </span>
  );
}

// ── Toast dispatcher ─────────────────────────────────────────────────────────
// App registers window.__pushToast; this helper is the public surface.
function pushToast(title, sub, kind) {
  if (window.__pushToast) window.__pushToast({ title, sub: sub || '', kind: kind || 'success' });
}

// ── Clerk-style login modal (mock) ──────────────────────────────────────────
function LoginModal({ onClose, onAuthed, identity }) {
  const [mode, setMode] = React.useState('signin'); // signin | signup
  const [email, setEmail] = React.useState('');
  const [busy, setBusy] = React.useState(null);

  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  const authViaSocial = (provider) => {
    setBusy(provider);
    setTimeout(() => { onAuthed(); pushToast('Signed in', 'Welcome back, ' + identity.nick, 'success'); }, 850);
  };
  const authViaEmail = (e) => {
    e.preventDefault();
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { pushToast('Invalid email', 'Enter a valid address', 'error'); return; }
    setBusy('email');
    setTimeout(() => { onAuthed(); pushToast('Signed in', 'Welcome, ' + identity.nick, 'success'); }, 850);
  };

  return (
    <div className="auth-scrim" onClick={onClose}>
      <div className="clerk-card" onClick={(e) => e.stopPropagation()}>
        <button className="clerk-x" onClick={onClose} title="Close">{window.ic.x}</button>
        <div className="clerk-body">
          <div className="clerk-logo"><window.BrandMark /></div>
          <h2 className="clerk-title">{mode === 'signin' ? 'Sign in to Archive' : 'Create your account'}</h2>
          <p className="clerk-sub">{mode === 'signin' ? 'Welcome back — pick a method to continue' : 'Join to submit games and post reviews'}</p>

          <div className="clerk-social">
            <button className="clerk-social-btn" onClick={() => authViaSocial('google')} disabled={!!busy}>
              {busy === 'google' ? <Spinner /> : ic2.google} Continue with Google
            </button>
            <button className="clerk-social-btn" onClick={() => authViaSocial('discord')} disabled={!!busy}>
              {busy === 'discord' ? <Spinner /> : ic2.discord} Continue with Discord
            </button>
          </div>

          <div className="clerk-divider">or</div>

          <form onSubmit={authViaEmail}>
            <div className="clerk-field">
              <label className="clerk-label">Email address</label>
              <input className="clerk-input" type="email" value={email} placeholder="you@example.com"
                     onChange={(e) => setEmail(e.target.value)} disabled={!!busy} />
            </div>
            <button className="clerk-primary" type="submit" disabled={!!busy}>
              {busy === 'email' ? <Spinner light /> : null}
              {mode === 'signin' ? 'Continue' : 'Create account'} {!busy && window.ic.arrow_r}
            </button>
          </form>

          <div className="clerk-secured">{ic2.lock} Secured by Clerk</div>
        </div>
        <div className="clerk-foot">
          {mode === 'signin'
            ? <>No account? <a onClick={() => setMode('signup')}>Sign up</a></>
            : <>Have an account? <a onClick={() => setMode('signin')}>Sign in</a></>}
        </div>
      </div>
    </div>
  );
}

function Spinner({ light }) {
  return <span className="cl-spin" style={{
    width: 14, height: 14, borderRadius: '50%', display: 'inline-block',
    border: '2px solid ' + (light ? 'rgba(255,255,255,.4)' : 'var(--border-strong)'),
    borderTopColor: light ? '#fff' : 'var(--accent)', animation: 'ts-spin .7s linear infinite'
  }} />;
}

// ── Sidebar account block ───────────────────────────────────────────────────
function AccountBlock({ auth, identity, onOpenLogin, onLogout, onView }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);

  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);

  if (auth === 'out') {
    return (
      <div className="acct">
        <button className="acct-login" onClick={onOpenLogin}>
          {ic2.login}<span>Login</span>
        </button>
      </div>
    );
  }

  const isAdmin = auth === 'admin';
  return (
    <div className="acct" ref={ref}>
      {open && (
        <div className="acct-menu">
          <div className="acct-menu-head">
            <Avatar identity={identity} size={30} />
            <div style={{ minWidth: 0 }}>
              <div className="nick">{identity.nick}</div>
              <div className="sub">{isAdmin ? 'Administrator' : 'Member'}</div>
            </div>
          </div>
          <button className="acct-menu-item" onClick={() => { setOpen(false); onView('mycontent'); }}>
            {ic2.inbox}<span>My Content</span>
          </button>
          <button className="acct-menu-item" onClick={() => { setOpen(false); onView('mycontent'); }}>
            {ic2.gear}<span>Account</span>
          </button>
          {isAdmin && (
            <a className="acct-menu-item" href={window.ADMIN_URL || 'admin.html'} target="_blank" rel="noopener noreferrer" onClick={() => setOpen(false)}>
              {ic2.shield}<span>Admin Dashboard</span>
              <span className="ext-hint">{window.ic.ext}</span>
            </a>
          )}
          <div className="acct-menu-sep" />
          <button className="acct-menu-item danger" onClick={() => { setOpen(false); onLogout(); }}>
            {ic2.logout}<span>Log Out</span>
          </button>
        </div>
      )}
      <button className={'acct-user' + (open ? ' open' : '')} onClick={() => setOpen((o) => !o)}>
        <Avatar identity={identity} size={26} />
        <div style={{ minWidth: 0 }}>
          <div className="nick">{identity.nick}</div>
          <div className="role">{isAdmin ? 'Administrator' : 'Member'}</div>
        </div>
        <span className="chev">{window.ic.chevron}</span>
      </button>
    </div>
  );
}

// ── Shared states: Skeleton / Empty / Error ─────────────────────────────────
function SkeletonList({ rows = 3 }) {
  return (
    <div>
      {Array.from({ length: rows }).map((_, i) => (
        <div className="skel-row" key={i}>
          <div className="skel" style={{ width: 30, height: 30, borderRadius: 7, flexShrink: 0 }} />
          <div style={{ flex: 1 }}>
            <div className="skel" style={{ width: '46%', height: 12, marginBottom: 8 }} />
            <div className="skel" style={{ width: '72%', height: 10 }} />
          </div>
          <div className="skel" style={{ width: 64, height: 20, borderRadius: 999 }} />
        </div>
      ))}
    </div>
  );
}

function EmptyState({ icon, title, sub }) {
  return (
    <div className="state-box">
      <div className="sx-ic">{icon || ic2.empty}</div>
      <h4>{title}</h4>
      {sub && <p>{sub}</p>}
    </div>
  );
}

function ErrorState({ title, sub, onRetry }) {
  return (
    <div className="state-box">
      <div className="sx-ic" style={{ color: 'oklch(0.62 0.16 25)' }}>{window.ic.warning}</div>
      <h4>{title || 'Something went wrong'}</h4>
      {sub && <p>{sub}</p>}
      {onRetry && <button className="doc-btn" style={{ marginTop: 12 }} onClick={onRetry}>{window.ic.refresh} Retry</button>}
    </div>
  );
}

// ── Turnstile mock ──────────────────────────────────────────────────────────
function Turnstile({ verified, onVerify }) {
  const [loading, setLoading] = React.useState(false);
  const trigger = () => {
    if (verified || loading) return;
    setLoading(true);
    setTimeout(() => { setLoading(false); onVerify(true); }, 900);
  };
  return (
    <div className="turnstile" onClick={trigger} role="checkbox" aria-checked={verified}>
      <div className={'turnstile-check' + (verified ? ' on' : '') + (loading ? ' loading' : '')}>
        {!loading && window.ic.check}
      </div>
      <span className="turnstile-label">{loading ? 'Verifying…' : verified ? 'Verified' : "I'm not a robot"}</span>
      <span className="turnstile-brand">CLOUDFLARE<br/>Privacy · Terms</span>
    </div>
  );
}

// Merge extra icons into the shared map and export.
Object.assign(window.ic, ic2);
Object.assign(window, {
  ic2, AVATAR_COLORS, genIdentity, loadIdentity, Avatar, pushToast,
  LoginModal, Spinner, AccountBlock, SkeletonList, EmptyState, ErrorState, Turnstile,
});
