const { useState, useEffect, useRef } = React;

/* Theme comes from the server (GET /campaign/active) and is applied on boot;
   useKioskTheme reflects whatever boot stored on window.GPS_KIOSK_THEME. */
function useKioskTheme() {
  const read = () =>
    window.GPS_KIOSK_THEME ||
    (window.GPSTheme ? window.GPSTheme.loadTheme() : { casinoName: "Riverwind", tagline: "Casino · Design Studio" });
  const [t, setT] = React.useState(read);
  React.useEffect(() => {
    const h = () => setT(read());
    window.addEventListener("kiosk-theme", h);
    return () => window.removeEventListener("kiosk-theme", h);
  }, []);
  return t;
}

function Landing({ onStart, onStaff, busy }) {
  const theme = useKioskTheme();
  return (
    <div className="kiosk" data-screen-label="Landing">
      <div className="frame-rule" />
      <button className="staff-btn" onClick={onStaff}>Staff</button>

      <header className="topbar">
        <div className="casino-logo anim d1">
          <div className="casino-mark"><span>LOGO</span></div>
          <div className="casino-text">
            <div className="name">{theme.casinoName}</div>
            <div className="loc">{theme.tagline}</div>
          </div>
        </div>
        <div className="reward-tag anim d1">Players Club</div>
      </header>

      <main className="hero">
        <div className="eyebrow anim d2">Design Studio</div>
        <h1 className="headline anim d3">
          Design Your Custom <em>Nikes</em>
        </h1>
        <p className="subtext anim d4">Create your one-of-a-kind pair. Start by checking in.</p>
        <div className="start-wrap anim d5">
          <button className="start-btn" onClick={onStart} disabled={busy}>
            {busy ? "Starting…" : "Start"}
            <span className="arrow">→</span>
          </button>
        </div>
      </main>

      <footer className="footer fade">
        <div className="by">Presented by</div>
        <div className="gps-wordmark"><b>GPS</b> Promotional Gifting Solutions</div>
      </footer>
    </div>
  );
}

/* Check-in form — logged the moment the guest starts. Styled to the kiosk. */
function Intake({ onSubmit, onBack }) {
  const theme = useKioskTheme();
  const [f, setF] = useState({ guestName: "", playerId: "", shoeSize: "", shoeGender: "" });
  const [err, setErr] = useState("");
  const set = (k) => (e) => setF((s) => ({ ...s, [k]: e.target.value }));
  const submit = (e) => {
    e.preventDefault();
    if (!f.guestName.trim() || !f.playerId.trim() || !f.shoeSize.trim() || !f.shoeGender) {
      setErr("Please fill in every field."); return;
    }
    setErr(""); onSubmit(f);
  };
  return (
    <div className="kiosk intake-screen" data-screen-label="Check In">
      <div className="frame-rule" />
      <header className="topbar">
        <div className="casino-logo anim d1">
          <div className="casino-mark"><span>LOGO</span></div>
          <div className="casino-text">
            <div className="name">{theme.casinoName}</div>
            <div className="loc">{theme.tagline}</div>
          </div>
        </div>
        <button className="gal-back" onClick={onBack}><span className="a">←</span> Back</button>
      </header>

      <main className="intake-main">
        <div className="intake-eyebrow anim d2">Check In</div>
        <h1 className="intake-title anim d3">Tell us about your fit</h1>
        <form className="intake-card anim d4" onSubmit={submit}>
          <label className="ik-field">
            <span>Full name</span>
            <input value={f.guestName} onChange={set("guestName")} autoFocus placeholder="Jane Doe" />
          </label>
          <label className="ik-field">
            <span>Player ID</span>
            <input value={f.playerId} onChange={set("playerId")} placeholder="Players-club number" />
          </label>
          <div className="ik-row">
            <label className="ik-field">
              <span>Shoe size</span>
              <input value={f.shoeSize} onChange={set("shoeSize")} placeholder="e.g. 10.5" inputMode="decimal" />
            </label>
            <div className="ik-field">
              <span>Fit</span>
              <div className="ik-seg">
                {["mens", "womens"].map((g) => (
                  <button type="button" key={g}
                    className={`ik-seg-btn${f.shoeGender === g ? " on" : ""}`}
                    onClick={() => setF((s) => ({ ...s, shoeGender: g }))}>
                    {g === "mens" ? "Men's" : "Women's"}
                  </button>
                ))}
              </div>
            </div>
          </div>
          {err && <div className="ik-err">{err}</div>}
          <button className="ik-submit" type="submit">Continue <span className="arrow">→</span></button>
        </form>
      </main>
    </div>
  );
}

function ShoeImg({ src, label, children }) {
  const [err, setErr] = useState(false);
  return (
    <div className="shoe-img">
      {src && !err
        ? <img src={src} alt={label} onError={() => setErr(true)} />
        : <span className="ph">{label} shot</span>}
      {children}
    </div>
  );
}

function Gallery({ shoes, onBack, onPick, busy }) {
  const theme = useKioskTheme();
  return (
    <div className="gallery" data-screen-label="Shoe Gallery">
      <header className="gal-header">
        <button className="gal-back" onClick={onBack}>
          <span className="a">←</span> Back
        </button>
        <h1 className="gal-title">Pick Your Shoe</h1>
        <div className="gift-badge"><span className="dot"></span> Let's design</div>
      </header>

      <div className="gal-scroll">
        <div className="sec-head approved-head">
          <div>
            <div className="sec-eyebrow" style={{ color: "var(--gold)" }}>{theme.casinoName} Players Club</div>
            <h2 className="sec-title">Choose your silhouette</h2>
          </div>
          <p className="sec-sub">Tap a shoe to open the Nike By You designer and make it yours.</p>
        </div>

        <div className="grid approved-grid">
          {shoes.map((s, i) => (
            <button key={s.id} className={`card card-x model-card pop p${i + 1}`} disabled={busy} onClick={() => onPick(s)}>
              <ShoeImg src={s.imageUrl} label={s.name} />
              <div className="card-body">
                <div className="shoe-name">{s.name}</div>
                <div className="model-cta">{busy ? "One sec…" : "Design your own"} <span>→</span></div>
              </div>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

/* Kiosk-shell handoff: a fixed status bar on top; the real Nike By You
   customizer fills the rest of the screen via the Electron BrowserView. The
   shell watches the clipboard + navigation for the share link and pushes it via
   gpsKiosk.onShareLink — we POST it to the backend against this guest's entry. */
function KioskHandoff({ shoe, guestName, entryId, nikeUrl, onCapture, onStartOver }) {
  const BAR = 92; // must match the y-offset passed to openNike
  const [saving, setSaving] = useState(false);
  const [msg, setMsg] = useState("Design your shoe below. When you're happy, tap Share → Copy Link on Nike.");
  const done = useRef(false);

  useEffect(() => {
    const k = window.gpsKiosk;
    if (k) k.openNike(nikeUrl, BAR, entryId);
    let unsub = null;
    if (k && k.onShareLink) {
      unsub = k.onShareLink(async (data) => {
        if (!data || data.entryId !== entryId || done.current) return;
        done.current = true;
        setSaving(true);
        setMsg("Saving your design…");
        try {
          // On success the parent closes the Nike view and shows the Thank-You page.
          await onCapture(data.url);
        } catch (e) {
          done.current = false;
          setSaving(false);
          setMsg(e.message || "Couldn't save — try Share → Copy Link again.");
        }
      });
    }
    return () => { if (unsub) unsub(); if (k) k.closeNike(); };
  }, []);

  return (
    <div style={{ position: "fixed", top: 0, left: 0, right: 0, height: BAR, background: "var(--navy, #0e1726)",
      color: "var(--cream,#f1f1ef)", display: "flex", alignItems: "center", gap: 18, padding: "0 20px",
      boxSizing: "border-box", borderBottom: "2px solid var(--gold,#c8a45c)", fontFamily: "var(--sans)", zIndex: 10 }}>
      <div style={{ display: "flex", flexDirection: "column", lineHeight: 1.15 }}>
        <span style={{ fontWeight: 900, letterSpacing: 0.5, fontSize: 18 }}><span style={{ color: "var(--gold,#c8a45c)" }}>G</span>PS Design Studio</span>
        <span style={{ fontSize: 12, opacity: 0.85 }}>{guestName} · {shoe ? shoe.name : "Nike By You"}</span>
      </div>
      <div style={{ padding: "8px 14px", borderRadius: 10, background: "rgba(255,255,255,.06)", border: "1px solid rgba(200,164,92,.5)", minWidth: 220 }}>
        <div style={{ fontSize: 14, fontWeight: 800, color: "var(--gold,#c8a45c)" }}>
          {saving ? "Saving…" : "○ Waiting for your design"}
        </div>
        <div style={{ fontSize: 11, color: "rgba(255,255,255,.7)" }}>Tap Share → Copy Link on Nike</div>
      </div>
      <div style={{ flex: 1, fontSize: 13, opacity: 0.9 }}>{msg}</div>
      <button onClick={onStartOver}
        style={{ padding: "12px 16px", borderRadius: 10, border: "1px solid rgba(255,255,255,.3)", background: "transparent",
          color: "inherit", cursor: "pointer", fontWeight: 700, fontSize: 13 }}>
        Start Over
      </button>
    </div>
  );
}

/* Browser fallback (no kiosk shell): open the customizer in a new tab and paste
   the share link. Also the way to exercise the whole flow without Electron. */
function DesignBrowser({ shoe, guestName, onCapture, onStartOver }) {
  const [pasted, setPasted] = useState("");
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState("");
  const builderUrl = (shoe && shoe.customUrl) || "https://www.nike.com/nike-by-you";
  const save = async () => {
    setSaving(true); setErr("");
    try { await onCapture(pasted.trim()); }
    catch (e) { setErr("That didn't look like a Nike share link. Use Share → Copy Link on Nike."); }
    finally { setSaving(false); }
  };
  return (
    <div className="gallery" data-screen-label="Design (browser)">
      <header className="gal-header">
        <button className="gal-back" onClick={onStartOver}><span className="a">←</span> Start over</button>
        <h1 className="gal-title">Design your {shoe ? shoe.name : "shoe"}</h1>
        <div className="gift-badge"><span className="dot"></span> {guestName}</div>
      </header>
      <div className="gal-scroll">
        <div className="db-steps">
          <ol>
            <li>Open the Nike By You customizer and design your shoe.</li>
            <li>Tap <b>Share → Copy Link</b> on Nike.</li>
            <li>Paste the link below to save it to <b>{guestName}</b>.</li>
          </ol>
          <a className="db-open" href={builderUrl} target="_blank" rel="noopener">Open Nike By You ↗</a>
          <input className="db-paste" value={pasted} onChange={(e) => setPasted(e.target.value)}
            placeholder="https://www.nike.com/u/…?mid=…" />
          {err && <div className="ik-err">{err}</div>}
          <button className="db-save" disabled={!pasted.trim() || saving} onClick={save}>
            {saving ? "Saving…" : "Save design"}
          </button>
        </div>
      </div>
    </div>
  );
}

/* After picking a silhouette: "Customize Your Own" (emphasized) vs. 2–3 prebuilt
   designs. Picking a prebuilt records its stored share link on the entry. */
function ChooseStyle({ shoe, busy, onBack, onCustomize, onPremade }) {
  const premades = shoe.premades || [];
  // Live share-link capture works for both Nike By You (mid) and Converse (metricId).
  const allowCustom = true;
  return (
    <div className="gallery" data-screen-label="Choose Style">
      <header className="gal-header">
        <button className="gal-back" onClick={onBack}><span className="a">←</span> Back</button>
        <h1 className="gal-title">{shoe.name}</h1>
        <div className="gift-badge"><span className="dot"></span> Let's design</div>
      </header>

      <div className="gal-scroll">
        {allowCustom && (
          <button className="customize-hero pop p1" onClick={onCustomize} disabled={busy}>
            <div className="ch-left">
              <div className="ch-eyebrow">Make it yours</div>
              <div className="ch-title">Customize Your Own</div>
              <div className="ch-sub">Open the designer — choose every color and detail, then share your design.</div>
            </div>
            <div className="ch-cta">{busy ? "One sec…" : "Start Designing"} <span>→</span></div>
          </button>
        )}

        {premades.length > 0 && <div className="style-or"><span>{allowCustom ? "Or pick a ready-made design" : "Pick a ready-made design"}</span></div>}

        <div className="grid premade-grid">
          {premades.map((pm, i) => (
            <article key={pm.id} className={`card card-x premade-card pop p${i + 2}`}>
              <ShoeImg src={pm.imageUrl} label={shoe.name}>
                {(pm.colors || []).length > 0 && (
                  <div className="pm-swatches">
                    {(pm.colors || []).map((c, j) => <span key={j} style={{ background: c }}></span>)}
                  </div>
                )}
              </ShoeImg>
              <div className="card-body">
                <div className="shoe-name">{pm.name}</div>
                <div className="ready-badge"><span className="chk">✓</span> Ready-made design</div>
                <button className="card-btn btn-primary" onClick={() => onPremade(pm)} disabled={busy}>
                  Pick This Pair
                </button>
              </div>
            </article>
          ))}
        </div>

        {!allowCustom && premades.length === 0 && (
          <div className="style-empty">Ready-made designs are coming soon for this style — please ask an attendant.</div>
        )}
      </div>
    </div>
  );
}

function ThankYou({ guestName, onDone }) {
  const theme = useKioskTheme();
  useEffect(() => {
    const id = setTimeout(onDone, 12000);
    return () => clearTimeout(id);
  }, []);
  return (
    <div className="thanks" data-screen-label="Thank You">
      <div className="ty-cobrand anim d1">
        <div className="casino-mark"><span>LOGO</span></div>
        <div className="ty-casino">{theme.casinoName}<span>{theme.tagline}</span></div>
      </div>
      <div className="seal anim d2">✓</div>
      <h1 className="anim d3">Your Design Is Saved!</h1>
      <p className="sub anim d4">Thanks{guestName ? `, ${guestName}` : ""} — your custom design is locked to your entry. Our team will take it from here.</p>
      <button className="done-btn anim d5" onClick={onDone}>Done — Next Guest</button>
      <div className="reset-note fade">This kiosk resets automatically for the next guest.</div>
    </div>
  );
}

function Unavailable({ onRetry }) {
  return (
    <div className="kiosk" data-screen-label="Unavailable">
      <div className="frame-rule" />
      <main className="hero">
        <div className="eyebrow anim d2">One moment</div>
        <h1 className="headline anim d3">Kiosk temporarily unavailable</h1>
        <p className="subtext anim d4">We're having trouble reaching the service. Please try again.</p>
        <div className="start-wrap anim d5">
          <button className="start-btn" onClick={onRetry}>Retry <span className="arrow">↻</span></button>
        </div>
      </main>
    </div>
  );
}

function App() {
  const [screen, setScreen] = useState("boot");
  const [catalog, setCatalog] = useState([]);
  const [campaign, setCampaign] = useState(null);
  const [intake, setIntake] = useState(null);   // the check-in form
  const [model, setModel] = useState(null);      // silhouette picked in the gallery
  const [shoe, setShoe] = useState(null);        // silhouette being designed
  const [entryId, setEntryId] = useState(null);
  const [busy, setBusy] = useState(false);
  const Admin = window.Admin;
  const inShell = !!(window.gpsKiosk && window.gpsKiosk.isKiosk);

  const boot = async () => {
    setScreen("boot");
    try {
      const data = await window.GPSApi.campaignActive();
      setCampaign(data.campaign);
      setCatalog(data.shoes || []);
      if (data.theme && window.GPSTheme) {
        window.GPS_KIOSK_THEME = data.theme;
        window.GPSTheme.applyTheme(data.theme);
        window.dispatchEvent(new CustomEvent("kiosk-theme", { detail: data.theme }));
      }
      setScreen((s) => (s === "boot" ? "landing" : s));
    } catch (e) {
      setScreen((s) => (s === "boot" ? "unavailable" : s));
    }
  };
  useEffect(() => { boot(); }, []);

  const resetToLanding = () => {
    if (entryId) { try { window.GPSApi.abandonEntry(entryId); } catch (e) {} }
    setEntryId(null); setIntake(null); setModel(null); setShoe(null);
    boot();
  };

  // Create the guest entry (intake + chosen silhouette). Returns the entry id.
  const beginEntry = async (form, chosenShoe) => {
    const res = await window.GPSApi.createEntry({ ...form, shoeId: chosenShoe ? chosenShoe.id : undefined });
    setEntryId(res.entryId);
    return res.entryId;
  };

  // "Customize Your Own": create the entry, open the live Nike By You designer.
  const startCustom = async (chosenShoe) => {
    setBusy(true);
    try {
      await beginEntry(intake, chosenShoe);
      setShoe(chosenShoe || null);
      setScreen("design");
    } catch (e) {
      alert(e.message || "Couldn't start your design — please try again.");
    } finally { setBusy(false); }
  };

  // Prebuilt design: create the entry, record the premade's stored share link.
  const startPremade = async (chosenShoe, pm) => {
    setBusy(true);
    try {
      const id = await beginEntry(intake, chosenShoe);
      await window.GPSApi.selectPremade(id, pm.id);
      setScreen("thankyou");
    } catch (e) {
      alert(e.message || "Couldn't save that design — please try again.");
    } finally { setBusy(false); }
  };

  const onIntake = (form) => {
    setIntake(form);
    if (catalog.length > 1) { setScreen("gallery"); }
    else if (catalog.length === 1) { setModel(catalog[0]); setScreen("style"); }
    else { beginEntry(form, null).then(() => { setShoe(null); setScreen("design"); }); } // no silhouettes → generic designer
  };

  const captureLink = async (url) => {
    await window.GPSApi.captureShareLink(entryId, url);
    // Close the Nike view (shell) and show the Thank-You page in both modes.
    if (inShell && window.gpsKiosk) { try { await window.gpsKiosk.closeNike(); } catch (e) {} }
    setScreen("thankyou");
  };

  if (screen === "admin") return <Admin onExit={() => boot()} />;
  if (screen === "boot") return <div className="kiosk" data-screen-label="Boot"><div className="frame-rule" /><main className="hero"><div className="eyebrow anim d2">Loading…</div></main></div>;
  if (screen === "unavailable") return <Unavailable onRetry={boot} />;
  if (screen === "thankyou") return <ThankYou guestName={intake ? intake.guestName : ""} onDone={resetToLanding} />;

  if (screen === "design" && entryId) {
    if (inShell) {
      return (
        <KioskHandoff
          shoe={shoe}
          guestName={intake ? intake.guestName : ""}
          entryId={entryId}
          nikeUrl={(shoe && shoe.customUrl) || "https://www.nike.com/nike-by-you"}
          onCapture={captureLink}
          onStartOver={resetToLanding}
        />
      );
    }
    return (
      <DesignBrowser
        shoe={shoe}
        guestName={intake ? intake.guestName : ""}
        onCapture={captureLink}
        onStartOver={resetToLanding}
      />
    );
  }

  if (screen === "style" && model) {
    return (
      <ChooseStyle
        shoe={model}
        busy={busy}
        onBack={() => (catalog.length > 1 ? setScreen("gallery") : resetToLanding())}
        onCustomize={() => startCustom(model)}
        onPremade={(pm) => startPremade(model, pm)}
      />
    );
  }

  if (screen === "gallery") {
    return <Gallery shoes={catalog} busy={busy} onBack={resetToLanding} onPick={(s) => { setModel(s); setScreen("style"); }} />;
  }

  if (screen === "intake") {
    return <Intake onSubmit={onIntake} onBack={resetToLanding} />;
  }

  return <Landing onStart={() => setScreen("intake")} onStaff={() => setScreen("admin")} busy={busy} />;
}

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