// App shell + router + Tweaks
const { useState: aS, useEffect: aE, useRef: aR } = React;

const DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#2A6FDB",
  "trialMinutes": 5,
  "price": 3,
  "showPricingOnLanding": true,
  "defaultLang": "uk"
}/*EDITMODE-END*/;

const INVITE_CODES = {
  "vlad-friends": "Vlad's friends",
  "vlad-beta": "Vlad's beta testers"
};

function MHApp() {
  const tw = (typeof useTweaks === "function") ? useTweaks(DEFAULTS) : [DEFAULTS, () => {}];
  const [tweaks, setTweak] = tw;

  // route: home | session | checkout | success | wallet
  const ROUTES = ["home", "session", "checkout", "success", "wallet"];
  const [route, setRoute] = aS(() => {
    const h = (location.hash || "").replace("#", "");
    return ROUTES.includes(h) ? h : "home";
  });
  const nav = (to) => { setRoute(to); location.hash = to; window.scrollTo(0, 0); };
  window.MH_nav = nav;
  aE(() => {
    const onHash = () => {
      const h = (location.hash || "").replace("#", "");
      if (ROUTES.includes(h)) setRoute(h);
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  // ---- invite link: ?invite=CODE ----
  aE(() => {
    const params = new URLSearchParams(location.search);
    const code = params.get("invite");
    if (code && INVITE_CODES[code]) {
      window.MH_Auth.applyInvite(code);
      history.replaceState({}, "", location.pathname + location.hash);
    }
  }, []);

  // ---- login modal state ----
  const [loginOpen, setLoginOpen] = aS(false);
  const [pendingPurchase, setPendingPurchase] = aS(null); // 'single' | 'pack' | 'pro' | null
  const auth = (typeof useAuth === "function") ? useAuth() : { user: null, loading: false, credits: 0, plan: "free", invite: "" };
  const openLogin = (afterPurchase) => { setPendingPurchase(afterPurchase || null); setLoginOpen(true); };

  // Navigate to session on fresh sign-in (magic link or Google OAuth)
  // Skip if on success screen — user just paid and polling needs to complete first
  aE(() => {
    const handler = () => {
      if ((location.hash || '').replace('#', '') !== 'success') nav("session");
    };
    window.addEventListener('mh-signed-in', handler);
    return () => window.removeEventListener('mh-signed-in', handler);
  }, []);

  const [lang, setLang] = aS(() => localStorage.getItem("mh-lang") || tweaks.defaultLang || "uk");
  aE(() => localStorage.setItem("mh-lang", lang), [lang]);
  const t = window.I18N[lang] || window.I18N.uk;

  // persisted state
  const [context, setContextRaw] = aS(() => localStorage.getItem("mh-context") || "");
  const setContext = (v) => { setContextRaw(v); localStorage.setItem("mh-context", v); };
  const [company, setCompanyRaw] = aS(() => localStorage.getItem("mh-company") || "");
  const setCompany = (v) => { setCompanyRaw(v); localStorage.setItem("mh-company", v); };
  const [meetingType, setMeetingTypeRaw] = aS(() => localStorage.getItem("mh-mt") || t.session.types[0]);
  const setMeetingType = (v) => { setMeetingTypeRaw(v); localStorage.setItem("mh-mt", v); };
  // when lang changes, remap meeting type by index
  aE(() => {
    const allLangs = ["uk", "en", "ru"];
    for (const L of allLangs) {
      const types = window.I18N[L].session.types;
      const idx = types.indexOf(meetingType);
      if (idx >= 0) { setMeetingTypeRaw(t.session.types[idx]); return; }
    }
  }, [lang]);

  // session unlocked = invited OR pro OR credits available OR just paid
  const [justPaid, setJustPaid] = aS(false);
  const unlocked = !!auth.invite || auth.plan === "pro" || auth.credits > 0 || justPaid;

  // expose tweak values to non-react code
  window.MH_TRIAL_SECONDS = tweaks.trialMinutes * 60;
  // apply accent globally
  aE(() => {
    document.documentElement.style.setProperty("--accent", tweaks.accent);
    // derive hover (darker) and soft (light)
    document.documentElement.style.setProperty("--accent-hover", shade(tweaks.accent, -14));
    document.documentElement.style.setProperty("--accent-soft", tint(tweaks.accent, 0.92));
    document.documentElement.style.setProperty("--them", tweaks.accent);
  }, [tweaks.accent]);

  const goStart = () => nav("session");
  const goUnlock = () => nav("checkout");
  const buyPack = () => { if (!auth.user) { openLogin("pack"); return; } window.MH_Auth.addCredits(auth.user.id, 300, "300 min pack — $10"); window.MH_Auth.setPlan("pack"); nav("success"); };
  const buyPro = () => { if (!auth.user) { openLogin("pro"); return; } window.MH_Auth.setPlan("pro", "$19/mo"); nav("success"); };
  const buySingle = () => nav("checkout");
  const onPaid = () => { window.MH_Auth.addCredits(auth.user?.id, 60, "60 min — $" + tweaks.price); setJustPaid(true); nav("success"); };

  // when login completes with a pending purchase, finish it
  aE(() => {
    if (auth.user && pendingPurchase) {
      const p = pendingPurchase; setPendingPurchase(null);
      if (p === "pack") buyPack();
      else if (p === "pro") buyPro();
      else if (p === "single") buySingle();
    }
  }, [auth.user, pendingPurchase]);

  let screen;
  const openWallet = () => nav("wallet");
  if (route === "home") screen = <Landing t={t} lang={lang} setLang={setLang} onStart={goStart} onBuyPack={buyPack} onBuyPro={buyPro} onSignIn={() => openLogin()} onOpenWallet={openWallet} />;
  else if (route === "session") screen = <Session t={t} lang={lang} setLang={setLang} onCTAUnlock={goUnlock} onClose={() => nav("home")} unlocked={unlocked} meetingType={meetingType} setMeetingType={setMeetingType} context={context} setContext={setContext} company={company} setCompany={setCompany} onSignIn={() => openLogin()} onOpenWallet={openWallet} />;
  else if (route === "checkout") screen = <Checkout t={t} onBack={() => nav("session")} onPaid={onPaid} price={tweaks.price} />;
  else if (route === "success") screen = <Success t={t} onContinue={() => nav("session")} />;
  else if (route === "wallet") screen = <Wallet onBack={() => nav("home")} onBuyPack={buyPack} onBuyPro={buyPro} onBuySingle={buySingle} t={t} />;

  const TP = window.TweaksPanel || (() => null);
  const TSec = window.TweakSection || (() => null);
  const TSli = window.TweakSlider || (() => null);
  const TCol = window.TweakColor || (() => null);
  const TTog = window.TweakToggle || (() => null);
  const TSel = window.TweakSelect || (() => null);

  return (
    <React.Fragment>
      {screen}
      <TP title="Tweaks">
        <TSec title="Pricing">
          <TSli label="Price per call ($)" value={tweaks.price} min={1} max={20} step={1} onChange={(v) => setTweak("price", v)} />
          <TSli label="Free trial (minutes)" value={tweaks.trialMinutes} min={1} max={15} step={1} onChange={(v) => setTweak("trialMinutes", v)} />
        </TSec>
        <TSec title="Look">
          <TCol label="Accent color" value={tweaks.accent} options={["#2A6FDB", "#7C3AED", "#16A34A", "#E11D48", "#F59E0B"]} onChange={(v) => setTweak("accent", v)} />
          <TSel label="Default language" value={tweaks.defaultLang} options={[["uk", "Українська"], ["en", "English"], ["ru", "Русский"]]} onChange={(v) => setTweak("defaultLang", v)} />
        </TSec>
        <TSec title="Landing">
          <TTog label="Show pricing section" value={tweaks.showPricingOnLanding} onChange={(v) => setTweak("showPricingOnLanding", v)} />
        </TSec>
        <TSec title="Owner / share link">
          <div style={{ fontSize: 12.5, color: "#374151", lineHeight: 1.5, marginBottom: 8 }}>
            Your personal invite — share with friends, they get unlimited.
          </div>
          <div style={{ background: "#f3f4f6", border: "1px solid #e5e7eb", borderRadius: 8, padding: "8px 10px", fontFamily: "ui-monospace, monospace", fontSize: 12.5, marginBottom: 8, wordBreak: "break-all" }}>
            {location.origin + location.pathname}?invite=vlad-friends
          </div>
          <button className="btn btn-outline" style={{ width: "100%" }} onClick={() => { navigator.clipboard.writeText(location.origin + location.pathname + "?invite=vlad-friends"); }}>Copy invite link</button>
          <button className="btn btn-ghost" style={{ width: "100%", marginTop: 6 }} onClick={() => { window.MH_Auth.applyInvite("vlad-friends"); }}>Apply invite now (for testing)</button>
        </TSec>
        <TSec title="Demo controls">
          <div style={{ fontSize: 12.5, color: "#6b7280", lineHeight: 1.45 }}>
            On the session screen, click <b>Start</b> to play a scripted demo. The trial timer starts immediately; when it hits 0:00, the paywall appears.
          </div>
          <button style={{ marginTop: 10, width: "100%" }} className="btn btn-ghost" onClick={() => { localStorage.removeItem("mh-user"); localStorage.removeItem("mh-credits"); localStorage.removeItem("mh-plan"); localStorage.removeItem("mh-invite"); localStorage.removeItem("mh-history"); window.dispatchEvent(new Event("mh-auth-change")); setJustPaid(false); nav("home"); }}>Reset prototype</button>
        </TSec>
      </TP>
      <LoginModal open={loginOpen} onClose={() => setLoginOpen(false)} />
    </React.Fragment>
  );
}

// helpers — shade / tint a hex color
function hexToRgb(h) { const m = h.replace("#", "").match(/.{2}/g) || ["00","00","00"]; return m.map(x => parseInt(x, 16)); }
function rgbToHex(r,g,b) { return "#" + [r,g,b].map(x => Math.max(0, Math.min(255, Math.round(x))).toString(16).padStart(2, "0")).join(""); }
function shade(hex, pct) { // pct in percent; negative = darker
  const [r,g,b] = hexToRgb(hex); const f = pct / 100;
  return rgbToHex(r + (255 - r) * (f > 0 ? f : 0) + r * (f < 0 ? f : 0), g + (255 - g) * (f > 0 ? f : 0) + g * (f < 0 ? f : 0), b + (255 - b) * (f > 0 ? f : 0) + b * (f < 0 ? f : 0));
}
function tint(hex, t) { // 0..1 toward white
  const [r,g,b] = hexToRgb(hex);
  return rgbToHex(r + (255 - r) * t, g + (255 - g) * t, b + (255 - b) * t);
}

ReactDOM.createRoot(document.getElementById("app")).render(<MHApp />);
