// Main app shell — sidebar nav, top bar, screen routing
const { useState: useState_app, useEffect: useEffect_app, useRef: useRef_app } = React;

// ---- Force-change-password screen — shown after login if must_change_password = true ----
function ChangePasswordScreen({ store, onDone, onLogout, recoveryMode }) {
  const [newPw, setNewPw]       = useState_app("");
  const [confirmPw, setConfirm] = useState_app("");
  const [showPw, setShowPw]     = useState_app(false);
  const [loading, setLoading]   = useState_app(false);
  const [error, setError]       = useState_app(null);

  const submit = async () => {
    if (!newPw.trim()) return setError("กรุณากรอกรหัสผ่านใหม่");
    if (newPw.length < 8) return setError("รหัสผ่านต้องมีอย่างน้อย 8 ตัวอักษร");
    if (newPw !== confirmPw) return setError("รหัสผ่านไม่ตรงกัน");
    setLoading(true);
    setError(null);
    try {
      await window.SBData.changePassword(newPw);
      store.setMustChangePassword(false);
      onDone();
    } catch (e) {
      setError(e.message || "เปลี่ยนรหัสผ่านไม่สำเร็จ — ลองใหม่อีกครั้ง");
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="auth-screen" data-screen-label="ChangePassword">
      <div className="auth-card">
        <div className="auth-logo"><Icon name="lock" size={26} stroke={1.8} /></div>
        <h1 className="auth-title">ตั้งรหัสผ่านใหม่</h1>
        <p className="auth-sub">{recoveryMode ? "กรอกรหัสผ่านใหม่ที่ต้องการตั้ง" : "กรุณาตั้งรหัสผ่านของคุณเองก่อนเข้าใช้งาน"}</p>
        {error && (
          <div style={{background:"rgba(255,59,48,0.1)", color:"var(--red)", borderRadius:8, padding:"10px 14px", marginBottom:12, fontSize:14}}>
            {error}
          </div>
        )}
        <div className="field">
          <label>รหัสผ่านใหม่</label>
          <input type={showPw ? "text" : "password"} value={newPw}
            onChange={e => setNewPw(e.target.value)}
            placeholder="อย่างน้อย 8 ตัวอักษร"
            autoFocus autoComplete="new-password" />
        </div>
        <div className="field">
          <label>ยืนยันรหัสผ่าน</label>
          <input type={showPw ? "text" : "password"} value={confirmPw}
            onChange={e => setConfirm(e.target.value)}
            placeholder="กรอกรหัสผ่านอีกครั้ง"
            autoComplete="new-password"
            onKeyDown={e => e.key === "Enter" && !loading && submit()} />
        </div>
        <div style={{display:"flex", alignItems:"center", gap:8, marginBottom:16}}>
          <input type="checkbox" id="cpw-show" checked={showPw} onChange={e => setShowPw(e.target.checked)} style={{width:14,height:14}} />
          <label htmlFor="cpw-show" style={{cursor:"pointer", fontSize:13, color:"var(--text-2)"}}>แสดงรหัสผ่าน</label>
        </div>
        <button className="btn primary lg block" onClick={submit} disabled={loading}>
          {loading ? "กำลังบันทึก…" : "ตั้งรหัสผ่านและเข้าสู่ระบบ"}
        </button>
        <button className="btn block" style={{marginTop:8}} onClick={onLogout}>
          ออกจากระบบ
        </button>
      </div>
      <div style={{position:"absolute", bottom:16, left:0, right:0, textAlign:"center", display:"flex", flexDirection:"column", gap:4, alignItems:"center", padding:"0 16px"}}>
        <div style={{color:"var(--text-3)", fontSize:12}}>
          BadMatch · ระบบจับคู่ผู้เล่นแบดมินตันอย่างยุติธรรม
        </div>
        <BrandCredit variant="footer" />
      </div>
    </div>
  );
}

function App() {
  // Public share route: #share=TOKEN bypasses auth
  const [shareRoute, setShareRoute] = useState_app(() => {
    const m = (location.hash || "").match(/#share=([\w-]+)/);
    return m ? m[1] : null;
  });
  useEffect_app(() => {
    const onHash = () => {
      const m = (location.hash || "").match(/#share=([\w-]+)/);
      setShareRoute(m ? m[1] : null);
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  const store = useStore();
  const [guestMode, setGuestMode] = useState_app(false);
  const [route, setRoute] = useState_app({ name: "dashboard" });
  // Public share loading state (anonymous viewers hydrate via loadShare RPC).
  const [shareStatus, setShareStatus] = useState_app("idle"); // idle | loading | ready | notfound
  const [createOpen, setCreateOpen] = useState_app(false);
  const [settingsOpen, setSettingsOpen] = useState_app(false);
  const [shareOpen, setShareOpen] = useState_app(false);
  const [profileOpen, setProfileOpen] = useState_app(false);
  const profileRef = useRef_app(null);
  const rtCleanup = useRef_app(null);
  const tour = useTour(store);

  // Apply the logged-in user's theme (profiles.theme) to <html data-theme> and cache
  // it so the inline pre-paint script picks it up on the next load. Runs after login /
  // session-restore (currentUser.theme arrives from the profile) and on every toggle.
  useEffect_app(() => {
    const t = store.currentUser?.theme;
    if (t === "light" || t === "dark") {
      document.documentElement.setAttribute("data-theme", t);
      try { localStorage.setItem("badmatch_theme", t); } catch (_) {}
    }
  }, [store.currentUser?.theme, store.currentUser?.id]);

  // Close profile popover on outside click
  useEffect_app(() => {
    if (!profileOpen) return;
    const handler = (e) => {
      if (profileRef.current && !profileRef.current.contains(e.target)) setProfileOpen(false);
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, [profileOpen]);
  // Live backend: show a brief boot screen while we restore the session.
  const [booting, setBooting] = useState_app(store.sbMode);
  // PASSWORD_RECOVERY mode — user landed via reset-password email link
  const [recoveryMode, setRecoveryMode] = useState_app(false);
  const recoveryRef = useRef_app(false);

  // Restore an existing Supabase session on first load (keeps user logged in across reloads).
  useEffect_app(() => {
    if (!store.sbMode) { setBooting(false); return; }
    let cancelled = false;

    // Subscribe to PASSWORD_RECOVERY before getSession so we don't accidentally
    // run the full login flow when the user lands via a reset-password link.
    const { data: { subscription } } = window.sb.auth.onAuthStateChange((event) => {
      if (event === "PASSWORD_RECOVERY" && !cancelled) {
        recoveryRef.current = true;
        setRecoveryMode(true);
        setBooting(false);
      }
    });

    (async () => {
      try {
        const u = await window.SBData.getSessionUser();
        if (u && !cancelled && !recoveryRef.current) {
          const payload = await window.SBData.loadAll();
          if (cancelled) return;
          store.hydrate(payload);
          store.setCurrentUser(u);
          rtCleanup.current = store.setupRealtime();
        }
      } catch (e) {
        console.error("[BadMatch] session restore failed:", e);
      } finally {
        if (!cancelled && !recoveryRef.current) setBooting(false);
      }
    })();
    return () => { cancelled = true; subscription?.unsubscribe?.(); };
  }, []);

  // Public share hydration — when on a #share route in live mode and the group
  // isn't already in the store, fetch it (and its players) via the public RPC.
  useEffect_app(() => {
    if (!shareRoute) { setShareStatus("idle"); return; }
    if (!store.sbMode) return; // demo mode: seed groups already in store
    if (store.groups.some(g => g.shareToken === shareRoute)) { setShareStatus("ready"); return; }
    let cancelled = false;
    setShareStatus("loading");
    (async () => {
      try {
        const res = await window.SBData.loadShare(shareRoute);
        if (cancelled) return;
        if (res && res.groups && res.groups.length) {
          store.hydrate({ groups: res.groups, players: res.players });
          setShareStatus("ready");
        } else {
          setShareStatus("notfound");
        }
      } catch (e) {
        console.error("[BadMatch] share load failed:", e);
        if (!cancelled) setShareStatus("notfound");
      }
    })();
    return () => { cancelled = true; };
  }, [shareRoute]);

  // Login handler — Supabase Auth when live, demo logic otherwise. Rejects on
  // failure so the login form can surface the message.
  async function doLogin(creds) {
    // creds.identifier may be a username OR an email (live mode resolves it).
    const identifier = creds.identifier || creds.email || "";
    if (store.sbMode) {
      const res = await window.SBData.signIn(identifier, creds.password || "");
      if (res.error || !res.user) throw new Error(res.error || "เข้าสู่ระบบไม่สำเร็จ");
      const u = res.user;
      if (u.role !== "super" && u.role !== "admin")
        throw new Error("บัญชีนี้ไม่มีสิทธิ์เข้าระบบ — ผู้ชมต้องใช้ลิงก์แชร์เท่านั้น");
      if (u.status && u.status !== "active") throw new Error("บัญชีถูกระงับ");
      if (u.expiry && new Date(u.expiry).getTime() < Date.now())
        throw new Error("บัญชีหมดอายุ — กรุณาติดต่อ Super User");
      const payload = await window.SBData.loadAll();
      store.hydrate(payload);
      store.setCurrentUser(u);
      rtCleanup.current = store.setupRealtime();
      return;
    }
    // ---- seed/demo fallback ----
    const idLower = identifier.toLowerCase();
    const found = store.users.find(u =>
      u.email.toLowerCase() === idLower ||
      (u.username && u.username.toLowerCase() === idLower)
    );
    if (!found) {
      store.setCurrentUser({
        id: "u-guest", name: identifier.split("@")[0], email: identifier,
        role: "admin", status: "active", expiry: null,
      });
      return;
    }
    if (found.role !== "super" && found.role !== "admin")
      throw new Error("บัญชีนี้ไม่มีสิทธิ์เข้าระบบ — ผู้ชมต้องใช้ลิงก์แชร์เท่านั้น");
    if (found.status !== "active") throw new Error("บัญชีถูกระงับ");
    if (found.expiry && new Date(found.expiry).getTime() < Date.now())
      throw new Error("บัญชีหมดอายุ — กรุณาติดต่อ Super User");
    store.setCurrentUser(found);
  }

  function doLogout() {
    if (rtCleanup.current) { rtCleanup.current(); rtCleanup.current = null; }
    if (store.sbMode) { try { window.SBData.signOut(); } catch (_) {} }
    store.setCurrentUser(null);
    setRoute({ name: "dashboard" });
  }

  // Public share view — no auth required. Anonymous viewers can't read tables
  // under RLS, so hydrate via the loadShare RPC (public-safe data only).
  if (shareRoute) {
    const shareGroupLoaded = store.groups.some(g => g.shareToken === shareRoute);
    // In live mode, hold the loading screen until the RPC resolves (or the group
    // is already hydrated) so we never mount the viewer with an undefined group.
    const shareWaiting = store.sbMode && !shareGroupLoaded &&
      (shareStatus === "idle" || shareStatus === "loading");
    return (
      <ToastHost>
        {shareWaiting ? (
          <div className="public-shell">
            <div className="public-empty">
              <div className="auth-logo"><Icon name="shuttle" size={26} stroke={1.8} /></div>
              <div className="muted" style={{marginTop: 12}}>กำลังโหลดหน้าดูสด…</div>
            </div>
          </div>
        ) : (
          <PublicShareView store={store} shareToken={shareRoute}
            onExit={() => { location.hash = ""; setShareRoute(null); }} />
        )}
      </ToastHost>
    );
  }

  // Guest mode gate — fully offline, no Supabase, no auth required
  if (guestMode) {
    return (
      <ToastHost>
        <GuestApp onExit={() => setGuestMode(false)} />
      </ToastHost>
    );
  }

  // Boot screen while restoring a live session
  if (booting) {
    return (
      <div className="auth-screen" data-screen-label="Boot">
        <div className="auth-card center">
          <div className="auth-logo"><Icon name="shuttle" size={26} stroke={1.8} /></div>
          <div className="muted" style={{marginTop: 12}}>กำลังเชื่อมต่อ…</div>
        </div>
      </div>
    );
  }

  // Password-recovery gate — user arrived via reset-password email link
  if (recoveryMode) {
    return (
      <ToastHost>
        <ChangePasswordScreen
          store={store}
          recoveryMode
          onDone={async () => {
            // After setting new password, restore session normally so user lands on dashboard.
            try {
              const u = await window.SBData.getSessionUser();
              if (u) {
                const payload = await window.SBData.loadAll();
                store.hydrate(payload);
                store.setCurrentUser(u);
                rtCleanup.current = store.setupRealtime();
              }
            } catch (_) {}
            setRecoveryMode(false);
          }}
          onLogout={() => { doLogout(); setRecoveryMode(false); }}
        />
      </ToastHost>
    );
  }

  // Auth gate — login screen
  if (!store.currentUser) {
    return (
      <ToastHost>
        <AuthScreen store={store} onAuth={doLogin} onGuestMode={() => setGuestMode(true)} />
      </ToastHost>
    );
  }

  // Force-change-password gate (live mode only) — priority over tutorial
  if (store.sbMode && store.mustChangePassword) {
    return (
      <ToastHost>
        <ChangePasswordScreen
          store={store}
          onDone={() => {}}
          onLogout={() => { doLogout(); }}
        />
      </ToastHost>
    );
  }

  const user = store.currentUser;
  const { can } = store;

  // Build nav based on role
  // Group Owners (admins) get: Dashboard, Players, Stats, Recommendations
  // Super Users add: Admin (audit/logs), Users, System Config
  const nav = [
    { id: "dashboard", label: "หน้าแรก", icon: "home" },
    { id: "groups",    label: "ก๊วน",    icon: "shuttle" },
    { id: "players",   label: "ผู้เล่น",  icon: "user" },
    { id: "stats",     label: "สถิติ",    icon: "bar" },
    can.manageGroups && { id: "viewers", label: "ผู้ชม", icon: "eye" },
    can.viewAllData && { id: "admin", label: "Admin", icon: "log" },
    can.manageUsers && { id: "users", label: "ผู้ใช้ระบบ", icon: "shield" },
    can.configRules && { id: "config", label: "System Config", icon: "settings" },
  ].filter(Boolean);

  const headers = {
    dashboard: "ภาพรวม",
    groups:    "ก๊วนของฉัน",
    group:     store.groups.find(g => g.id === route.id)?.name || "ก๊วน",
    players:   "ผู้เล่น",
    stats:     "สถิติ & คำแนะนำ",
    viewers:   "วิเคราะห์ผู้ชม",
    admin:     "ระบบหลังบ้าน",
    users:     "ผู้ใช้ระบบ",
    config:    "การตั้งค่าระบบ",
  };

  // Both super and admin can open any group (viewers don't log in)
  const currentGroup = route.name === "group" ? store.groups.find(g => g.id === route.id) : null;

  const screen = route.name === "group" && currentGroup
    ? <GroupSession store={store} groupId={route.id}
        onBack={() => setRoute({ name: "dashboard" })}
        onOpenSettings={() => setSettingsOpen(true)}
        onShare={() => setShareOpen(true)} />
    : route.name === "groups"  ? <GroupsScreen store={store} onOpenGroup={(id) => setRoute({ name: "group", id })} onCreateGroup={() => setCreateOpen(true)} />
    : route.name === "players" ? <PlayersScreen store={store} />
    : route.name === "stats"   ? <StatsScreen store={store} />
    : route.name === "viewers" ? <ViewerAnalyticsScreen store={store} />
    : route.name === "admin"   ? <AdminScreen store={store} />
    : route.name === "users"   ? <UsersScreen store={store} />
    : route.name === "config"  ? <SystemConfigScreen store={store} />
    : <Dashboard store={store}
        onOpenGroup={(id) => setRoute({ name: "group", id })}
        onCreateGroup={() => setCreateOpen(true)} />;

  return (
    <ToastHost>
      <div className="app">
        <aside className="sidebar">
          <div className="brand">
            <div className="brand-mark"><Icon name="shuttle" size={16} stroke={1.8} /></div>
            <div>
              <div className="brand-name">BadMatch</div>
              <div className="brand-sub">จับคู่ • จัดก๊วน • สถิติ</div>
            </div>
          </div>

          <div className="side-section side-section-main">
            <div className="side-label">เมนูหลัก</div>
            {nav.map(item => (
              <button key={item.id}
                data-tour={`nav-${item.id}`}
                className={`nav-item ${route.name === item.id || (item.id === "groups" && route.name === "group") ? "active" : ""}`}
                onClick={() => setRoute({ name: item.id })}>
                <span className="nav-icon"><Icon name={item.icon} size={18} /></span>
                {item.label}
              </button>
            ))}
          </div>

          <div className="side-section side-section-groups">
            <div className="side-label">ก๊วนล่าสุด</div>
            {store.visibleGroups.slice(0, 4).map(g => (
              <button key={g.id} className={`nav-item ${route.name==="group" && route.id===g.id ? "active" : ""}`}
                onClick={() => setRoute({ name: "group", id: g.id })}>
                <span className="dot" style={{background: g.color, width: 8, height: 8, marginLeft: 4, marginRight: 8}} />
                <span style={{whiteSpace:"nowrap", overflow:"hidden", textOverflow:"ellipsis"}}>{g.name}</span>
              </button>
            ))}
            {store.visibleGroups.length === 0 && (
              <div className="muted small" style={{padding: "6px 12px"}}>ยังไม่มีก๊วนของคุณ</div>
            )}
          </div>

          <div className="side-footer" style={{position:"relative"}} ref={profileRef}>
            <button className="profile-trigger" onClick={() => setProfileOpen(v => !v)} title="โปรไฟล์">
              <div className="avatar">{initials(user.name)}</div>
              <div className="grow" style={{minWidth:0, textAlign:"left"}}>
                <div style={{fontSize: 13, fontWeight:500, whiteSpace:"nowrap", overflow:"hidden", textOverflow:"ellipsis"}}>{user.name}</div>
                <div className="row gap-2" style={{minWidth:0}}>
                  <span className={`role-badge role-${user.role}`} style={{fontSize: 9, padding:"1px 6px"}}>
                    {roleLabel(user.role)}
                  </span>
                </div>
              </div>
              <Icon name="chevron" size={13} style={{color:"var(--text-3)", transform: profileOpen ? "rotate(180deg)" : "none", transition:"transform 0.15s"}} />
            </button>
            {profileOpen && (
              <div className="profile-popover">
                <div className="profile-pop-info">
                  <div style={{fontWeight:600}}>{user.name}</div>
                  <div className="small muted" style={{wordBreak:"break-all"}}>{user.email}</div>
                </div>
                <div className="profile-pop-divider" />
                <div className="profile-pop-theme">
                  <span className="profile-pop-theme-label">ธีมการแสดงผล</span>
                  <Segmented value={store.theme} onChange={store.setTheme}
                    options={[
                      { value: "light", label: "☀️ สว่าง" },
                      { value: "dark",  label: "🌙 มืด" },
                    ]} />
                </div>
                <div className="profile-pop-divider" />
                <button className="profile-pop-item" onClick={() => { tour.start(); setProfileOpen(false); }}>
                  <Icon name="help" size={14} /> ดูวิธีใช้งาน (Tutorial)
                </button>
                <div className="profile-pop-divider" />
                <button className="profile-pop-item danger" onClick={() => { setProfileOpen(false); doLogout(); }}>
                  <Icon name="door" size={14} /> ออกจากระบบ
                </button>
              </div>
            )}
          </div>

          <div className="side-credit" style={{padding:"8px 12px 4px", textAlign:"center"}}>
            <BrandCredit variant="inline" />
          </div>
        </aside>

        <main className="main">
          <div className="topbar">
            <h1>{headers[route.name] || "BadMatch"}</h1>
            <div className="topbar-actions">
              {route.name === "group" && currentGroup && can.shareGroup && (
                <button className="btn sm" onClick={() => setShareOpen(true)} title="แชร์หน้าดูสด">
                  <Icon name="eye" size={13} /> แชร์
                </button>
              )}
              {route.name === "group" && currentGroup && can.manageGroups && (
                <button className="btn icon" onClick={() => setSettingsOpen(true)} title="ตั้งค่าก๊วน">
                  <Icon name="settings" size={15} />
                </button>
              )}
            </div>
            {/* Mobile only — sidebar footer (name + logout) is hidden on small screens */}
            <div className="topbar-user">
              <div className="avatar" style={{width:28, height:28, fontSize:11, flexShrink:0}}>
                {initials(user.name)}
              </div>
              <div className="topbar-user-info">
                <div className="topbar-user-name">{user.name}</div>
                <span className={`role-badge role-${user.role}`} style={{fontSize:9, padding:"1px 5px"}}>
                  {roleLabel(user.role)}
                </span>
              </div>
              <button className="btn icon" onClick={() => store.setTheme(store.theme === "dark" ? "light" : "dark")}
                      title={store.theme === "dark" ? "สลับเป็นโหมดสว่าง" : "สลับเป็นโหมดมืด"}>
                <Icon name={store.theme === "dark" ? "sun" : "moon"} size={15} />
              </button>
              <button className="btn icon" onClick={doLogout} title="ออกจากระบบ">
                <Icon name="door" size={15} />
              </button>
            </div>
          </div>
          <div className="scroll">
            {screen}
          </div>
        </main>

        {createOpen && can.manageGroups && <CreateGroupModal store={store}
          onClose={() => setCreateOpen(false)}
          onCreated={(id) => { setCreateOpen(false); setRoute({ name: "group", id }); }} />}

        {settingsOpen && currentGroup && (
          <GroupSettingsModal group={currentGroup}
            updateGroup={store.updateGroup} deleteGroup={store.deleteGroup}
            systemConfig={store.systemConfig}
            canCustomizeViewer={store.can.customizeViewer}
            onClose={() => setSettingsOpen(false)}
            onDeleted={() => { setSettingsOpen(false); setRoute({ name: "dashboard" }); }}
            onShare={() => setShareOpen(true)} />
        )}

        {shareOpen && currentGroup && (
          <ShareModal group={currentGroup} store={store} onClose={() => setShareOpen(false)} />
        )}

        {/* Tutorial Tour overlay */}
        {tour.open && (
          <TourOverlay
            step={tour.step}
            total={TOUR_STEPS.length}
            stepData={TOUR_STEPS[tour.step]}
            onNext={tour.next}
            onPrev={tour.prev}
            onClose={tour.close}
          />
        )}
      </div>
    </ToastHost>
  );
}

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