// components.jsx — shared UI for the FRAMEDROP landing
// Exports to window: Placeholder, Icon, Logo, Nav, Ticker, FilterBar,
//   LaunchCard, LaunchGrid, Newsletter, Footer, Meta

// ── Striped art placeholder ──────────────────────────────────────────────
function Placeholder({ label, ratio, tall }) {
  return (
    <div className="ph" style={ratio ? { aspectRatio: ratio } : tall ? { height: '100%' } : undefined}>
      <div className="ph-stripes" />
      <div className="ph-grid" />
      <span className="ph-label">{label}</span>
    </div>
  );
}

// ── Minimal inline icons (simple paths only) ─────────────────────────────
function Icon({ name, size = 16 }) {
  const p = {
    arrow: <path d="M5 12h14M13 6l6 6-6 6" />,
    arrowUR: <path d="M7 17 17 7M9 7h8v8" />,
    search: <><circle cx="11" cy="11" r="7" /><path d="m20 20-3.2-3.2" /></>,
    bookmark: <path d="M6 4h12v16l-6-4-6 4z" />,
    play: <path d="M8 5v14l11-7z" />,
    spark: <path d="M12 3v6M12 15v6M3 12h6M15 12h6" />,
    clock: <><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></>,
  };
  return (
    <svg className="ico" width={size} height={size} viewBox="0 0 24 24" fill="none"
         stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"
         aria-hidden="true">{p[name]}</svg>
  );
}

function Logo() {
  return (
    <a className="logo" href="#top" aria-label="FRAMEDROP home">
      <span className="logo-mark"><i /><i /></span>
      <span className="logo-word">FRAME<b>DROP</b></span>
    </a>
  );
}

// ── Top navigation ────────────────────────────────────────────────────────
function Nav({ onReadLatest }) {
  const links = ['Launches', 'Reviews', 'Hardware', 'Guides', 'Esports'];
  return (
    <header className="nav" id="top">
      <div className="nav-inner">
        <Logo />
        <nav className="nav-links">
          {links.map((l, i) => (
            <a key={l} href="#latest" className={i === 0 ? 'active' : ''}>{l}</a>
          ))}
        </nav>
        <div className="nav-right">
          <button className="icon-btn" aria-label="Search"><Icon name="search" size={18} /></button>
          <button className="btn btn-primary" onClick={onReadLatest}>
            Read latest <Icon name="arrow" size={15} />
          </button>
        </div>
      </div>
    </header>
  );
}

// ── Release ticker strip ────────────────────────────────────────────────
function Ticker() {
  const items = [
    ['Aether Drift', 'OUT NOW'],
    ['Ashveil', 'JUN 11'],
    ['Pulse Circuit', 'JUN 14'],
    ['Vanguard Protocol', 'JUN 20'],
    ['Mooncradle', 'JUL 02'],
    ['Garden of Static', 'JUL 09'],
  ];
  const row = items.concat(items);
  return (
    <div className="ticker" aria-hidden="true">
      <div className="ticker-track">
        {row.map((it, i) => (
          <span className="ticker-item" key={i}>
            <em>{it[1]}</em>{it[0]}
            <i className="ticker-dot" />
          </span>
        ))}
      </div>
    </div>
  );
}

// ── Meta line (author · date · read) ────────────────────────────────────
function Meta({ author, date, read }) {
  return (
    <div className="meta">
      <span className="meta-avatar" aria-hidden="true">{author.split(' ').map((w) => w[0]).join('')}</span>
      <span className="meta-name">{author}</span>
      <span className="meta-sep">/</span>
      <span>{date}</span>
      <span className="meta-sep">/</span>
      <span className="meta-read"><Icon name="clock" size={13} /> {read}</span>
    </div>
  );
}

// ── Category filter ─────────────────────────────────────────────────────
function FilterBar({ cats, active, onPick }) {
  return (
    <div className="filterbar" role="tablist">
      {cats.map((c) => (
        <button key={c} role="tab" aria-selected={c === active}
                className={'chip' + (c === active ? ' chip-on' : '')}
                onClick={() => onPick(c)}>{c}</button>
      ))}
    </div>
  );
}

// ── Launch card ─────────────────────────────────────────────────────────
function LaunchCard({ item, saved, onSave }) {
  return (
    <article className="card">
      <div className="card-art">
        <Placeholder label={'// ' + item.title} ratio="16 / 10" />
        <span className={'tag tag-' + item.tag.toLowerCase().replace(/\s/g, '')}>{item.tag}</span>
        {item.score && <span className="score"><b>{item.score}</b><i>/10</i></span>}
        <button className={'save' + (saved ? ' save-on' : '')} aria-pressed={saved}
                aria-label={saved ? 'Saved' : 'Save'} onClick={() => onSave(item.id)}>
          <Icon name="bookmark" size={16} />
        </button>
      </div>
      <div className="card-body">
        <span className="card-genre">{item.genre}</span>
        <h3 className="card-title">{item.title}</h3>
        <p className="card-blurb">{item.blurb}</p>
        <div className="card-foot">
          <span>{item.author}</span>
          <span className="meta-sep">·</span>
          <span>{item.date}</span>
          <span className="card-read">Read <Icon name="arrow" size={14} /></span>
        </div>
      </div>
    </article>
  );
}

function LaunchGrid({ items, saved, onSave }) {
  return (
    <div className="grid">
      {items.map((it) => (
        <LaunchCard key={it.id} item={it} saved={saved.has(it.id)} onSave={onSave} />
      ))}
    </div>
  );
}

// ── Newsletter band ─────────────────────────────────────────────────────
function Newsletter() {
  const [email, setEmail] = React.useState('');
  const [state, setState] = React.useState('idle'); // idle | error | done
  const submit = (e) => {
    e.preventDefault();
    if (/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) setState('done');
    else setState('error');
  };
  return (
    <section className="news">
      <div className="news-inner">
        <div className="news-copy">
          <span className="eyebrow">// patch_notes.weekly</span>
          <h2>Every launch, in your inbox before the servers go live.</h2>
          <p>One email a week. New releases, review verdicts, and the patches that actually matter. No filler.</p>
        </div>
        {state === 'done' ? (
          <div className="news-done">
            <span className="news-check"><Icon name="arrow" size={18} /></span>
            You're in. First drop lands Monday.
          </div>
        ) : (
          <form className={'news-form' + (state === 'error' ? ' err' : '')} onSubmit={submit} noValidate>
            <input type="email" placeholder="player@frame.gg" value={email}
                   onChange={(e) => { setEmail(e.target.value); setState('idle'); }} />
            <button className="btn btn-primary" type="submit">Subscribe <Icon name="arrow" size={15} /></button>
            {state === 'error' && <span className="news-err">Enter a valid email</span>}
          </form>
        )}
      </div>
    </section>
  );
}

// ── Footer ──────────────────────────────────────────────────────────────
function Footer() {
  const cols = [
    ['Sections', ['Launches', 'Reviews', 'Hardware', 'Guides', 'Esports']],
    ['Company', ['About', 'Writers', 'Ethics policy', 'Contact']],
    ['Follow', ['Discord', 'YouTube', 'Bluesky', 'RSS']],
  ];
  return (
    <footer className="footer">
      <div className="footer-inner">
        <div className="footer-brand">
          <Logo />
          <p>Where game launches land first. Independent coverage, no review codes attached.</p>
        </div>
        <div className="footer-cols">
          {cols.map(([h, items]) => (
            <div key={h} className="footer-col">
              <h4>{h}</h4>
              {items.map((i) => <a key={i} href="#top">{i}</a>)}
            </div>
          ))}
        </div>
      </div>
      <div className="footer-base">
        <span>© 2026 FRAMEDROP</span>
        <span className="footer-mono">build 26.06 · made for players</span>
      </div>
    </footer>
  );
}

Object.assign(window, {
  Placeholder, Icon, Logo, Nav, Ticker, Meta, FilterBar,
  LaunchCard, LaunchGrid, Newsletter, Footer,
});
