// app.jsx — entry point, view switcher, tweaks

const _TWEAK_BASE = /*EDITMODE-BEGIN*/{
  "view": "admin",
  "freelancerName": "Donna",
  "freelancerTitle": "Founder & Creative Director",
  "brandName": "TrendVibe Creatives",
  "accent": "#1B4332",
  "currency": "USD",
  "demoClientId": "veltrix",
  "defaultRate": 1500
}/*EDITMODE-END*/;

// Merge saved tweaks from localStorage so brand/name survive page refresh
const TWEAK_DEFAULTS = (() => {
  try {
    const saved = localStorage.getItem("relay_v1_tweaks");
    return saved ? { ..._TWEAK_BASE, ...JSON.parse(saved) } : _TWEAK_BASE;
  } catch { return _TWEAK_BASE; }
})();

function DemoSwitcher({ view, setView, clientId, setClientId, clients }) {
  return (
    <div className="demo-bar">
      <span className="demo-dot"/>
      <span className="demo-label">Relay demo</span>
      <button className={view === "admin" ? "active" : ""} onClick={() => setView("admin")}>Admin (You)</button>
      <button className={view === "client" ? "active" : ""} onClick={() => setView("client")}>Client view</button>
      {view === "client" && (
        <>
          <span style={{ width: 1, height: 18, background: "rgba(255,255,255,0.15)", margin: "0 6px" }}/>
          <select value={clientId} onChange={e => setClientId(e.target.value)}
            style={{ background: "transparent", color: "#fff", border: 0, fontSize: 12, padding: "4px 8px", borderRadius: 6, cursor: "pointer" }}>
            {clients.map(c => <option key={c.id} value={c.id} style={{ color: "#000" }}>{c.company}</option>)}
          </select>
        </>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Firebase Auth — gates the Admin view behind Google sign-in
// ─────────────────────────────────────────────────────────────────────
let _fbAuth = null;
function getFirebaseAuth() {
  if (_fbAuth) return _fbAuth;
  const cfg = window.RELAY_CONFIG && window.RELAY_CONFIG.firebase;
  if (!cfg || !window.firebase) return null;
  try {
    if (!window.firebase.apps.length) window.firebase.initializeApp(cfg);
    _fbAuth = window.firebase.auth();
    return _fbAuth;
  } catch (e) { return null; }
}
window.relayAuthUser = () => { const a = getFirebaseAuth(); return a && a.currentUser; };
window.relaySignOut = () => { const a = getFirebaseAuth(); if (a) a.signOut(); };

// SHA-256 helper for the client access code
async function sha256Hex(str) {
  const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(str));
  return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, "0")).join("");
}
window.sha256Hex = sha256Hex;

// Client access-code gate — shown on the public portal so only people you
// give the code to can open it.
function ClientCodeGate({ children }) {
  const hash = (window.RELAY_CONFIG && window.RELAY_CONFIG.clientAccessCodeHash) || "";
  // Admin previewing their own client portal (set by "Open as client") skips the gate.
  const adminPreview = (() => { try { return localStorage.getItem("relay_admin_preview") === "1"; } catch { return false; } })();
  const [unlocked, setUnlocked] = React.useState(() => {
    if (adminPreview) return true;
    if (!hash) return true; // no code configured → open
    try { return localStorage.getItem("relay_client_unlocked") === hash; } catch { return false; }
  });
  const [input, setInput] = React.useState("");
  const [err, setErr] = React.useState("");
  const [busy, setBusy] = React.useState(false);

  if (unlocked) return children;

  const submit = async () => {
    if (!input.trim()) return;
    setBusy(true); setErr("");
    try {
      const h = await sha256Hex(input.trim().toLowerCase());
      if (h === hash.toLowerCase()) {
        try { localStorage.setItem("relay_client_unlocked", hash); } catch {}
        setUnlocked(true);
      } else {
        setErr("That code doesn't match. Double-check the code from your invite.");
      }
    } catch (e) { setErr("Something went wrong — try again."); }
    finally { setBusy(false); }
  };

  return (
    <div style={{ minHeight: "100vh", display: "grid", placeItems: "center", background: "var(--bg)", padding: 24 }}>
      <div className="card card-pad fade-up" style={{ maxWidth: 400, width: "100%", textAlign: "center" }}>
        <div className="col gap-16" style={{ alignItems: "center" }}>
          <LogoMark size={40} color="var(--primary)"/>
          <div className="col gap-4">
            <div className="h-display" style={{ fontSize: 26 }}>Welcome</div>
            <div className="ink-3" style={{ fontSize: 13.5, lineHeight: 1.5 }}>Enter the access code from your invite to open your private onboarding portal.</div>
          </div>
          <input className="input" value={input} autoFocus
            onChange={e => setInput(e.target.value)}
            onKeyDown={e => e.key === "Enter" && submit()}
            placeholder="Access code"
            style={{ textAlign: "center", fontSize: 15, letterSpacing: "0.04em" }}/>
          <button onClick={submit} disabled={busy} className="btn btn-primary btn-lg" style={{ width: "100%", justifyContent: "center" }}>
            {busy ? "Checking…" : "Open my portal"}
          </button>
          {err && <div style={{ fontSize: 12, color: "var(--danger)", lineHeight: 1.4 }}>{err}</div>}
        </div>
      </div>
    </div>
  );
}

function AuthScreen({ mode, email, error, onSignIn, onSignOut }) {
  const { brandName } = TWEAK_DEFAULTS;
  return (
    <div style={{ minHeight: "100vh", display: "grid", placeItems: "center", background: "var(--bg)", padding: 24 }}>
      <div className="card card-pad fade-up" style={{ maxWidth: 400, width: "100%", textAlign: "center" }}>
        <div className="col gap-16" style={{ alignItems: "center" }}>
          <LogoMark size={40} color="var(--primary)"/>
          {mode === "loading" && (
            <>
              <div style={{ width: 22, height: 22, border: "2px solid var(--primary)", borderTopColor: "transparent", borderRadius: "50%", animation: "spin 0.8s linear infinite" }}/>
              <div className="ink-3" style={{ fontSize: 13 }}>Checking your session…</div>
              <style>{`@keyframes spin{to{transform:rotate(360deg)}}`}</style>
            </>
          )}
          {mode === "signedout" && (
            <>
              <div className="col gap-4">
                <div className="h-display" style={{ fontSize: 26 }}>Admin sign-in</div>
                <div className="ink-3" style={{ fontSize: 13.5, lineHeight: 1.5 }}>This dashboard is private. Sign in with your Google account to continue.</div>
              </div>
              <button onClick={onSignIn} className="btn btn-lg" style={{ width: "100%", justifyContent: "center", gap: 10, background: "#fff", border: "1px solid var(--line)" }}>
                <svg width="18" height="18" viewBox="0 0 48 48"><path fill="#EA4335" d="M24 9.5c3.5 0 6.6 1.2 9 3.6l6.8-6.8C35.6 2.4 30.2 0 24 0 14.6 0 6.4 5.4 2.5 13.3l7.9 6.1C12.3 13.3 17.6 9.5 24 9.5z"/><path fill="#4285F4" d="M46.1 24.5c0-1.6-.1-3.1-.4-4.5H24v9h12.4c-.5 2.9-2.1 5.3-4.6 7l7.1 5.5c4.2-3.9 6.6-9.6 6.6-16.5z"/><path fill="#FBBC05" d="M10.4 28.6c-.5-1.5-.8-3-.8-4.6s.3-3.1.8-4.6l-7.9-6.1C.9 16.5 0 20.1 0 24s.9 7.5 2.5 10.7l7.9-6.1z"/><path fill="#34A853" d="M24 48c6.5 0 11.9-2.1 15.9-5.8l-7.1-5.5c-2 1.3-4.5 2.1-8.8 2.1-6.4 0-11.7-3.8-13.6-9.4l-7.9 6.1C6.4 42.6 14.6 48 24 48z"/></svg>
                Sign in with Google
              </button>
              {error && <div style={{ fontSize: 12, color: "var(--danger)", lineHeight: 1.4 }}>{error}</div>}
            </>
          )}
          {mode === "denied" && (
            <>
              <div className="col gap-4">
                <div className="h-display" style={{ fontSize: 24 }}>No access</div>
                <div className="ink-3" style={{ fontSize: 13, lineHeight: 1.5 }}>
                  <span className="mono">{email}</span> isn't on the admin list for this portal.
                </div>
              </div>
              <button onClick={onSignOut} className="btn" style={{ width: "100%", justifyContent: "center" }}>Sign out & try another account</button>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

function AuthGate({ children }) {
  const auth = getFirebaseAuth();
  const adminEmails = ((window.RELAY_CONFIG && window.RELAY_CONFIG.adminEmails) || []).map(e => String(e).toLowerCase());
  // Auth not configured (e.g. local dev without Firebase) → don't block.
  const [phase, setPhase] = React.useState(() => auth ? "loading" : "open");
  const [user, setUser] = React.useState(null);
  const [error, setError] = React.useState("");

  React.useEffect(() => {
    if (!auth) return;
    const unsub = auth.onAuthStateChanged((u) => {
      setUser(u);
      if (!u) setPhase("signedout");
      else if (adminEmails.length && !adminEmails.includes(String(u.email || "").toLowerCase())) setPhase("denied");
      else setPhase("open");
    });
    return () => unsub();
  }, [auth]);

  const signIn = async () => {
    setError("");
    try {
      const provider = new window.firebase.auth.GoogleAuthProvider();
      await auth.signInWithPopup(provider);
    } catch (e) {
      const code = e && e.code;
      if (code === "auth/operation-not-allowed") setError("Google sign-in isn't enabled yet in the Firebase console (Authentication → Sign-in method → Google).");
      else if (code === "auth/popup-closed-by-user" || code === "auth/cancelled-popup-request") setError("");
      else setError(String((e && e.message) || e));
    }
  };
  const signOut = () => auth && auth.signOut();

  if (phase === "open") return children;
  if (phase === "loading") return <AuthScreen mode="loading"/>;
  if (phase === "denied") return <AuthScreen mode="denied" email={user && user.email} onSignOut={signOut}/>;
  return <AuthScreen mode="signedout" onSignIn={signIn} error={error}/>;
}

function AdminApp() {
  const [view, setView] = React.useState("dashboard");
  const { freelancer } = useApp();
  return (
    <AdminShell view={view} setView={setView} freelancer={freelancer}>
      {view === "dashboard" && <AdminDashboard goTo={setView}/>}
      {view === "clients" && <AdminClients goTo={setView}/>}
      {view === "client-detail" && <AdminClientDetail goTo={setView}/>}
      {view === "new" && <AdminNewClient goTo={setView}/>}
      {view === "templates" && <AdminTemplates/>}
      {view === "inbox" && <AdminInbox/>}
      {view === "settings" && <AdminSettings/>}
    </AdminShell>
  );
}

function ClientApp() {
  const { activeClientId, setActiveClientId } = useApp();
  return <ClientPortal clientId={activeClientId}/>;
}

function Root() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  return (
    <ToastProvider>
      <AppProvider tweaks={t}>
        <RootInner tweaks={t} setTweak={setTweak}/>
      </AppProvider>
    </ToastProvider>
  );
}

// Production = the live deployed site (not localhost). Add ?prod=1 to test
// production behavior locally.
const _params = new URLSearchParams(typeof location !== "undefined" ? location.search : "");
const IS_PROD = (typeof location !== "undefined" &&
  location.hostname !== "localhost" && location.hostname !== "127.0.0.1") || _params.has("prod");
// On the live site, a client link uses ?portal (or ?client=<id>); everything
// else lands on the Google-gated admin.
const URL_WANTS_CLIENT = _params.has("portal") || _params.has("client");
const URL_CLIENT_ID = _params.get("client");

function RootInner({ tweaks: t, setTweak }) {
  const { clients, activeClientId, setActiveClientId } = useApp();

  // In production, the view is decided by the URL (no demo bar to toggle).
  const view = IS_PROD ? (URL_WANTS_CLIENT ? "client" : "admin") : t.view;

  // Persist tweaks to localStorage whenever they change
  React.useEffect(() => {
    try { localStorage.setItem("relay_v1_tweaks", JSON.stringify(t)); } catch {}
  }, [t]);

  // sync active client id with tweak
  React.useEffect(() => {
    if (t.demoClientId && t.demoClientId !== activeClientId) {
      setActiveClientId(t.demoClientId);
    }
  }, [t.demoClientId]);

  // Honor ?client=<slug-or-id> on the live site to open a specific client's portal.
  // Accepts both the new slug (kgp-consultants) and the legacy raw id (veltrix).
  React.useEffect(() => {
    if (!URL_CLIENT_ID) return;
    const match = findClientByKey(clients, URL_CLIENT_ID);
    if (match) setActiveClientId(match.id);
    else setActiveClientId(URL_CLIENT_ID); // fallback so the no-client screen can show
  }, [clients]);

  const clientView = IS_PROD ? <ClientCodeGate><ClientApp/></ClientCodeGate> : <ClientApp/>;

  return (
    <>
      {!IS_PROD && (
        <DemoSwitcher
          view={t.view} setView={v => setTweak("view", v)}
          clientId={activeClientId}
          setClientId={(id) => { setActiveClientId(id); setTweak("demoClientId", id); }}
          clients={clients}
        />
      )}

      <div style={{ paddingTop: IS_PROD ? 0 : 56 }}>
        {view === "admin" ? <AuthGate><AdminApp/></AuthGate> : clientView}
      </div>

      {!IS_PROD && <TweaksPanel title="Tweaks">
        <TweakSection label="View"/>
        <TweakRadio label="Side" value={t.view} options={["admin","client"]} onChange={v => setTweak("view", v)}/>
        {t.view === "client" && (
          <TweakSelect label="Demo client" value={t.demoClientId}
            options={clients.map(c => ({ value: c.id, label: c.company }))}
            onChange={v => { setTweak("demoClientId", v); setActiveClientId(v); }}/>
        )}

        <TweakSection label="Brand"/>
        <TweakText label="Freelancer name" value={t.freelancerName} onChange={v => setTweak("freelancerName", v)}/>
        <TweakText label="Title" value={t.freelancerTitle} onChange={v => setTweak("freelancerTitle", v)}/>
        <TweakText label="Brand" value={t.brandName} onChange={v => setTweak("brandName", v)}/>
        <TweakColor label="Accent" value={t.accent}
          options={["#1B4332", "#0F1A14", "#2C4D8A", "#8A5E2C", "#B23A2E", "#5B3F8A"]}
          onChange={v => setTweak("accent", v)}/>

        <TweakSection label="Defaults"/>
        <TweakSelect label="Currency" value={t.currency}
          options={[{ value: "USD", label: "USD ($)" }, { value: "EUR", label: "EUR (€)" }, { value: "GBP", label: "GBP (£)" }, { value: "PHP", label: "PHP (₱)" }, { value: "CAD", label: "CAD" }, { value: "AUD", label: "AUD" }]}
          onChange={v => setTweak("currency", v)}/>
        <TweakNumber label="Default rate" value={t.defaultRate} min={50} max={20000} step={50} onChange={v => setTweak("defaultRate", v)}/>
      </TweaksPanel>}

      <style>{`
        :root { --primary: ${t.accent}; }
        .demo-bar .demo-dot { background: #80E0A7; }
      `}</style>
    </>
  );
}

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