// Auth — Discord OAuth2 + Steam OpenID linking.
//
// In production (when on shovelhead.net), this uses real OAuth via the
// API worker at api.shovelhead.net (see backend/api-worker.js).
// In any other origin (this design app, localhost, etc.) it falls back
// to the mock popups so the UI can be exercised without a backend.

const SH_AUTH_KEY = "shovelhead.session.v1";

// Detect production. Real OAuth only fires when both:
//   - hostname is shovelhead.net / www.shovelhead.net
//   - SHOVELHEAD_CONFIG.discordClientId is set
function isProduction() {
  const h = window.location.hostname;
  return h === "shovelhead.net" || h === "www.shovelhead.net";
}
function apiBase() {
  return (window.SHOVELHEAD_CONFIG?.pinsApiUrl || "").replace(/\/$/, "");
}

function readSession() {
  try {
    const raw = localStorage.getItem(SH_AUTH_KEY);
    const s = raw ? JSON.parse(raw) : { discord: null, steam: null, tier: null, priorityUntil: null };
    // Backwards compat: previous version stored the full tier object — normalize to key string.
    if (s.tier && typeof s.tier === "object") s.tier = s.tier.key || null;
    return s;
  } catch { return { discord: null, steam: null, tier: null, priorityUntil: null }; }
}
function writeSession(s) {
  localStorage.setItem(SH_AUTH_KEY, JSON.stringify(s));
  window.dispatchEvent(new CustomEvent("shovelheadauth", { detail: s }));
}

// ── Hydrate session from server on page load (production only) ───────────
// The session cookie is HTTP-only so JS can't read it directly — we ask
// the API for the user's info using credentials: "include". If a valid
// session exists, mirror its user data into the local session shape.
async function hydrateFromServer() {
  if (!isProduction()) return;
  const api = apiBase();
  if (!api) return;
  try {
    const r = await fetch(api + "/auth/me", { credentials: "include" });
    if (!r.ok) return;
    const j = await r.json();
    if (j.authenticated && j.user) {
      const prev = readSession();
      const discord = {
        id:       j.user.discordId,
        username: j.user.username,
        avatarHash: j.user.avatar || null,
        globalName: j.user.globalName || null,
        staff:     !!j.user.staff,
        staffTier: j.user.staffTier || null,
        joinedAt: prev.discord?.joinedAt || Date.now(),
      };
      const steam = j.user.steamId ? {
        steamId64:   j.user.steamId,
        personaName: j.user.steamPersonaName || prev.steam?.personaName || null,
        avatarHash:  j.user.steamAvatar      || null,
        linkedAt:    prev.steam?.linkedAt || Date.now(),
      } : null;
      const next = { ...prev, discord, steam };
      // Only write if something actually changed.
      if (JSON.stringify(prev.discord) !== JSON.stringify(discord) ||
          JSON.stringify(prev.steam)   !== JSON.stringify(steam)) {
        writeSession(next);
      }
    } else {
      // Server says not logged in — clear any stale local session.
      const prev = readSession();
      if (prev.discord || prev.steam) {
        writeSession({ ...prev, discord: null, steam: null });
      }
    }
  } catch (e) {
    console.warn("[shovelhead] /auth/me failed:", e.message);
  }
}
// Run on first load.
hydrateFromServer();

function useAuth() {
  const [session, setSession] = React.useState(readSession);
  React.useEffect(() => {
    const onChange = e => setSession(e.detail);
    window.addEventListener("shovelheadauth", onChange);
    return () => window.removeEventListener("shovelheadauth", onChange);
  }, []);
  return {
    session,
    signInDiscord: async () => {
      if (isProduction() && apiBase()) {
        // Kick off the real OAuth flow — full-page redirect.
        const returnTo = window.location.href;
        const url = new URL(apiBase() + "/auth/discord/start");
        url.searchParams.set("returnTo", returnTo);
        window.location.href = url.toString();
        return;
      }
      // Local / preview: mock popup
      await fakeOAuthPopup("discord");
      const seed = Math.random().toString(36).slice(2, 8);
      const next = { ...readSession(), discord: {
        id: "1" + Math.floor(Math.random() * 1e17).toString(),
        username: ["nightowl","dustbin","ColdSpoon","palletjack","gravelmouth","ConcreteHymn"][Math.floor(Math.random()*6)] + "_" + seed.slice(0,3),
        avatarSeed: seed,
        joinedAt: Date.now(),
      }};
      writeSession(next);
    },
    signOutDiscord: async () => {
      if (isProduction() && apiBase()) {
        try { await fetch(apiBase() + "/auth/logout", { method: "POST", credentials: "include" }); }
        catch {}
      }
      writeSession({ ...readSession(), discord: null, steam: null, tier: null, priorityUntil: null });
    },
    linkSteam: async () => {
      if (isProduction() && apiBase()) {
        // Real Steam OpenID redirect.
        const returnTo = window.location.href;
        const url = new URL(apiBase() + "/auth/steam/start");
        url.searchParams.set("returnTo", returnTo);
        window.location.href = url.toString();
        return;
      }
      // Local / preview: mock popup
      await fakeOAuthPopup("steam");
      const next = { ...readSession(), steam: {
        steamId64: "765611980" + Math.floor(Math.random() * 1e8).toString().padStart(8, "0"),
        personaName: ["FrostByteFred","Mort.404","Vinegar_Saint","Hollow.Tide","Pyre_Walker"][Math.floor(Math.random()*5)],
        avatarSeed: Math.random().toString(36).slice(2, 8),
        linkedAt: Date.now(),
      }};
      writeSession(next);
    },
    unlinkSteam: () => writeSession({ ...readSession(), steam: null }),
    purchaseTier: async (tier, days) => {
      await fakePayPalCheckout(tier);
      const until = Date.now() + days * 24 * 3600 * 1000;
      writeSession({ ...readSession(), tier: tier.key, priorityUntil: until });
    },
    cancelTier: () => writeSession({ ...readSession(), tier: null, priorityUntil: null }),
  };
}

// ── Mock overlays ───────────────────────────────────────────────────────
function fakeOAuthPopup(provider) {
  return new Promise(resolve => {
    const el = document.createElement("div");
    el.className = "fake-oauth";
    el.innerHTML = `
      <div class="fake-oauth-card">
        <div class="fake-oauth-brand">${provider === "discord" ? "Discord" : "STEAM"}</div>
        <div class="fake-oauth-title">Authorize ShovelHead.net?</div>
        <div class="fake-oauth-perms">
          ${provider === "discord"
            ? "<li>Read your username and avatar</li><li>Add you to the ShovelHead.net server</li><li>Manage your roles</li>"
            : "<li>Confirm your Steam ID</li><li>Read your public profile name</li>"}
        </div>
        <div class="fake-oauth-actions">
          <button class="btn" data-cancel>Cancel</button>
          <button class="btn btn-primary" data-ok>Authorize</button>
        </div>
        <div class="fake-oauth-note">SIMULATED · No real OAuth call is made in this prototype.</div>
      </div>
    `;
    document.body.appendChild(el);
    requestAnimationFrame(() => el.classList.add("on"));
    el.querySelector("[data-cancel]").onclick = () => { el.remove(); resolve(false); };
    el.querySelector("[data-ok]").onclick = () => {
      el.querySelector(".fake-oauth-card").innerHTML = `<div class="fake-oauth-spin"></div><div class="fake-oauth-title">Authorizing…</div>`;
      setTimeout(() => { el.remove(); resolve(true); }, 900);
    };
  });
}

function fakePayPalCheckout(tier) {
  return new Promise(resolve => {
    const el = document.createElement("div");
    el.className = "fake-oauth";
    el.innerHTML = `
      <div class="fake-oauth-card paypal">
        <div class="fake-oauth-brand paypal"><span>Pay</span><span>Pal</span></div>
        <div class="fake-oauth-title">Subscribe — ${tier.label} · $${tier.price}/mo</div>
        <div class="fake-oauth-pp-row">
          <div class="lbl">PAYPAL</div>
          <div class="val">survivor•••@shovelhead.net</div>
        </div>
        <div class="fake-oauth-pp-row">
          <div class="lbl">FUNDING</div>
          <div class="val">PayPal balance · backup: Visa •••• 4242</div>
        </div>
        <div class="fake-oauth-pp-row">
          <div class="lbl">BILLING</div>
          <div class="val">$${tier.price}.00 / month · cancel anytime</div>
        </div>
        <div class="fake-oauth-actions">
          <button class="btn" data-cancel>Cancel</button>
          <button class="btn btn-paypal" data-ok>Subscribe with PayPal</button>
        </div>
        <div class="fake-oauth-note">SIMULATED · No charge is made. In production this is the PayPal Subscriptions flow.</div>
      </div>
    `;
    document.body.appendChild(el);
    requestAnimationFrame(() => el.classList.add("on"));
    el.querySelector("[data-cancel]").onclick = () => { el.remove(); resolve(false); };
    el.querySelector("[data-ok]").onclick = () => {
      el.querySelector(".fake-oauth-card").innerHTML = `<div class="fake-oauth-spin"></div><div class="fake-oauth-title">Processing payment…</div>`;
      setTimeout(() => { el.remove(); resolve(true); }, 1200);
    };
  });
}

window.useAuth = useAuth;
