const { useState, useEffect, useRef, useMemo } = React;

const SUPABASE_URL = "https://zczgbohvtocbaiyrsqne.supabase.co";
const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inpjemdib2h2dG9jYmFpeXJzcW5lIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1NTIyMTIsImV4cCI6MjA5NDEyODIxMn0.-2nYtnMDTjsFFD56mXBCMoLB7hizRI7GbW5wFhrp9eA";

const rateLimiter = { attempts: [], maxAttempts: 3, windowMs: 60000 };

function checkRateLimit() {
  const now = Date.now();
  rateLimiter.attempts = rateLimiter.attempts.filter(t => now - t < rateLimiter.windowMs);
  if (rateLimiter.attempts.length >= rateLimiter.maxAttempts) return false;
  rateLimiter.attempts.push(now);
  return true;
}

function sanitizeEmail(raw) {
  const trimmed = raw.trim().toLowerCase().slice(0, 254);
  const pattern = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
  if (!pattern.test(trimmed)) return null;
  const [, domain] = trimmed.split("@");
  if (!domain || !domain.includes(".") || domain.endsWith(".")) return null;
  return trimmed;
}

async function submitToWaitlist(email, honeypot) {
  if (honeypot) throw new Error("Something went wrong. Try again.");
  if (!checkRateLimit()) throw new Error("Too many attempts. Try again in a minute.");
  const clean = sanitizeEmail(email);
  if (!clean) throw new Error("That email doesn't look right.");
  const res = await fetch(`${SUPABASE_URL}/rest/v1/waitlist`, {
    method: "POST",
    headers: {
      "apikey": SUPABASE_ANON_KEY,
      "Authorization": `Bearer ${SUPABASE_ANON_KEY}`,
      "Content-Type": "application/json",
      "Prefer": "return=minimal",
    },
    body: JSON.stringify({ email: clean }),
  });
  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    if (err.code === "23505") throw new Error("You're already on the list!");
    throw new Error("Something went wrong. Try again.");
  }
}

function Nav({ onJoin }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const on = () => setScrolled(window.scrollY > 20);
    on();
    window.addEventListener("scroll", on, { passive: true });
    return () => window.removeEventListener("scroll", on);
  }, []);
  return (
    <nav className={"nav" + (scrolled ? " nav-scrolled" : "")}>
      <div className="nav-inner page">
        <a href="#top" className="nav-brand">
          <span className="dot"></span>
          <span className="nav-wordmark">What's Poppin'</span>
        </a>
        <div className="nav-right">
          <span className="pill nav-pill">Closed Beta · '26</span>
          <button onClick={onJoin} className="nav-cta">
            Join waitlist
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
          </button>
        </div>
      </div>
    </nav>
  );
}

function WaitlistForm({ onSubmit, compact = false }) {
  const [email, setEmail] = useState("");
  const [err, setErr] = useState("");
  const [loading, setLoading] = useState(false);
  const [hp, setHp] = useState("");
  const submit = async (e) => {
    e.preventDefault();
    if (!/^\S+@\S+\.\S+$/.test(email)) { setErr("That email doesn't look right."); return; }
    setErr("");
    setLoading(true);
    try {
      await submitToWaitlist(email, hp);
      onSubmit(email);
    } catch (ex) {
      setErr(ex.message);
    } finally {
      setLoading(false);
    }
  };
  return (
    <form className={"form " + (compact ? "form-compact" : "")} onSubmit={submit} noValidate>
      <input type="text" name="website" value={hp} onChange={(e) => setHp(e.target.value)} tabIndex={-1} style={{ position: "absolute", left: "-9999px", opacity: 0, height: 0, width: 0, overflow: "hidden" }} autoComplete="off" aria-hidden="true" />
      <div className="form-row">
        <div className="form-field">
          <input
            type="email"
            placeholder="you@email.com"
            value={email}
            onChange={(e) => { setEmail(e.target.value); setErr(""); }}
            aria-label="Email"
            autoComplete="email"
            maxLength={254}
          />
        </div>
        <button type="submit" className="btn-primary form-submit" disabled={loading}>
          {loading ? "Joining..." : "Claim my spot"}
          {!loading && <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M5 12h14M13 5l7 7-7 7"/></svg>}
        </button>
      </div>
      <div className="form-meta">
        {err ? <span className="form-err">{err}</span> : (
          <>
            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>
            <span>No spam. One email when we open Chicago.</span>
          </>
        )}
      </div>
    </form>
  );
}

function Counter() {
  const [n, setN] = useState(427);
  useEffect(() => {
    const id = setInterval(() => setN(v => v + (Math.random() > 0.6 ? 1 : 0)), 4500);
    return () => clearInterval(id);
  }, []);
  return <span className="counter">{n.toLocaleString()}</span>;
}

function Hero({ onJoin }) {
  return (
    <section className="hero">
      <div className="page hero-inner">
        <div className="hero-copy">
          <div className="hero-eyebrow">
            <span className="dot"></span>
            <span><Counter /> on the list · Chicago, 2026</span>
          </div>

          <h1 className="display hero-headline">
            What's Poppin'?<br/>
            <span className="green">You tell us.</span>
          </h1>

          <p className="lede hero-lede">
            Stop texting <em>"where you at?"</em> See which bars are live, dead, or trending — right now, in real time, from the people inside.
          </p>

          <div className="hero-form">
            <WaitlistForm onSubmit={onJoin} />
          </div>

          <div className="hero-proof">
            <div className="proof-stack">
              <div className="proof-bar" aria-hidden="true">
                <span></span><span></span><span></span><span></span><span></span>
              </div>
              <div>
                <div className="proof-num"><Counter /> on the list</div>
                <div className="proof-sub">Mostly Chicago. Mostly 21–28. Mostly out tonight.</div>
              </div>
            </div>
          </div>
        </div>

        <div className="hero-phone">
          <RotatingPhone />
        </div>
      </div>
    </section>
  );
}

function HowItWorks() {
  const steps = [
    { n: "01", t: "Open the map", b: "See every bar, club, and house spot nearby — colored by how live they are right now." },
    { n: "02", t: "Check the hype", b: "Real updates from people inside. Crowd, music, line, vibe — under a minute old." },
    { n: "03", t: "Pull up", b: "Pick the move. Drop a pin when you get there. Help the next person decide." },
  ];
  return (
    <section className="section">
      <div className="page">
        <div className="section-head">
          <span className="eyebrow">How it works</span>
          <h2 className="h2">Three taps.<br/><span className="serif italic">That's it.</span></h2>
        </div>
        <div className="steps">
          {steps.map((s, i) => (
            <div className="step" key={i}>
              <div className="step-num">{s.n}</div>
              <div className="step-line" aria-hidden="true"></div>
              <h3 className="step-title">{s.t}</h3>
              <p className="step-body">{s.b}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function Chicago() {
  const hoods = ["Wicker Park", "Logan Square", "River North", "West Loop", "Fulton Market", "Pilsen", "Lincoln Park", "Ukrainian Village", "Bucktown"];
  return (
    <section className="section section-chicago">
      <div className="page chicago-grid">
        <div className="chicago-meta">
          <span className="eyebrow">First wave</span>
          <h2 className="h2 chicago-headline">
            We start in<br/>
            <span className="green serif italic">Chicago.</span>
          </h2>
          <p className="lede">
            One city. Done right. Real users, real venues, real updates — before we touch anywhere else.
          </p>
          <div className="chicago-coords mono">
            41.8781° N · 87.6298° W
          </div>
        </div>
        <div className="chicago-card card">
          <div className="chicago-card-head">
            <span className="eyebrow" style={{ color: "var(--green-bright)" }}>
              <span className="dot"></span>
              Seeding now
            </span>
            <span className="mono chicago-card-sub">9 neighborhoods</span>
          </div>
          <div className="chicago-hoods">
            {hoods.map((h, i) => (
              <span className="hood" key={i}>
                <span className="hood-dot"></span>
                {h}
              </span>
            ))}
          </div>
          <div className="chicago-footnote mono">
            Not in Chicago? Drop your email — we'll come to you next.
          </div>
        </div>
      </div>
    </section>
  );
}

function Testimonials() {
  const messages = [
    { from: "Maya", at: "Logan Square", text: "ok this is the app i've been begging for", green: true },
    { from: "Devon", at: "Wicker Park", text: "no more group chat polls at 11pm 🙏" },
    { from: "Alex", at: "West Loop", text: "literally saved my friday — Aviary was dead, Estereo was popping", green: true },
    { from: "Jordan", at: "River North", text: "shut up and take my email" },
    { from: "Priya", at: "Pilsen", text: "this is what citizen but for the function should be", green: true },
    { from: "Sam", at: "Fulton Market", text: "the hype score is genuinely accurate??" },
  ];
  const [idx, setIdx] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setIdx(i => (i + 2) % messages.length), 4200);
    return () => clearInterval(id);
  }, []);
  const visible = [
    messages[idx % messages.length],
    messages[(idx + 1) % messages.length],
  ];
  return (
    <section className="section section-testimonials">
      <div className="page">
        <div className="section-head section-head-center">
          <span className="eyebrow">From the group chat</span>
          <h2 className="h2">Word's already<br/><span className="serif italic green">getting out.</span></h2>
        </div>
        <div className="bubbles">
          {visible.map((m, i) => (
            <div className={"bubble " + (m.green ? "bubble-green" : "")} key={idx + "-" + i} style={{ animationDelay: (i * 0.1) + "s" }}>
              <p className="bubble-text">{m.text}</p>
              <div className="bubble-meta">
                <span className="bubble-from">{m.from}</span>
                <span className="bubble-sep">·</span>
                <span>{m.at}</span>
              </div>
            </div>
          ))}
        </div>
        <div className="bubbles-note mono">
          Real DMs from the beta. Names changed. Energy didn't.
        </div>
      </div>
    </section>
  );
}

function FinalCTA({ onJoin }) {
  return (
    <section className="section section-final">
      <div className="page final-inner">
        <div className="final-icon" aria-hidden="true">
          <svg width="42" height="42" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
            <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
          </svg>
        </div>
        <h2 className="display final-headline">
          Don't miss<br/>
          <span className="green">what's poppin'.</span>
        </h2>
        <div className="final-form">
          <WaitlistForm onSubmit={onJoin} compact />
        </div>
        <div className="final-meta mono">
          <Counter /> already in · Free, forever, to join
        </div>
      </div>
    </section>
  );
}

function Footer() {
  return (
    <footer className="footer">
      <div className="page footer-inner mono">
        <span>© 2026 What's Poppin'</span>
        <span className="footer-sep">·</span>
        <span>Built in Chicago</span>
        <span className="footer-sep">·</span>
        <span>Made for the night owls</span>
      </div>
    </footer>
  );
}

function SuccessOverlay({ open, email, onClose, position }) {
  if (!open) return null;
  const handle = email.split("@")[0];
  return (
    <div className="success-overlay" onClick={onClose}>
      <div className="success-card" onClick={(e) => e.stopPropagation()}>
        <button className="success-close" onClick={onClose} aria-label="Close">×</button>
        <div className="success-check">
          <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
            <path d="M20 6L9 17l-5-5"/>
          </svg>
        </div>
        <div className="success-eyebrow mono">You're in</div>
        <div className="success-number">#{position.toLocaleString()}</div>
        <p className="success-body">
          We'll email <span className="success-email">{handle}</span> the moment Chicago goes live.
        </p>
        <div className="success-share-label mono">Move up the line</div>
        <div className="success-share">
          <button className="share-btn">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
            Share on X
          </button>
          <button className="share-btn">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1" fill="currentColor"/></svg>
            Share to IG
          </button>
        </div>
        <div className="success-footnote mono">
          Every friend who joins bumps you up 5 spots.
        </div>
      </div>
    </div>
  );
}

function App() {
  const [success, setSuccess] = useState(false);
  const [email, setEmail] = useState("");
  const [position, setPosition] = useState(428);

  const handleJoin = (e) => {
    setEmail(e);
    setPosition(Math.floor(Math.random() * 30) + 410);
    setSuccess(true);
  };

  const scrollToForm = () => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  return (
    <>
      <div className="atmos"></div>
      <div className="grid-bg"></div>
      <Nav onJoin={scrollToForm} />
      <main id="top">
        <Hero onJoin={handleJoin} />
        <HowItWorks />
        <Chicago />
        <Testimonials />
        <FinalCTA onJoin={handleJoin} />
      </main>
      <Footer />
      <div className="grain"></div>
      <SuccessOverlay open={success} email={email} position={position} onClose={() => setSuccess(false)} />
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
