// ARS Service Management — App shell, sidebar, routing
const { useState, useEffect, useMemo } = React;

// ─── Error Boundary ──────────────────────────────────────────────
class ErrorBoundary extends React.Component {
  constructor(props) { super(props); this.state = { error: null }; }
  static getDerivedStateFromError(err) { return { error: err }; }
  componentDidCatch(err, info) { console.error("React render error:", err, info); }
  render() {
    if (this.state.error) {
      return (
        <div style={{ padding: 40, fontFamily: "monospace", background: "#fff1f2", minHeight: "100vh" }}>
          <div style={{ maxWidth: 700, margin: "0 auto" }}>
            <h2 style={{ color: "#dc2626", marginBottom: 12 }}>⚠ App Error</h2>
            <p style={{ color: "#666", marginBottom: 16 }}>กรุณาส่ง error ด้านล่างให้ทีม support</p>
            <pre style={{ background: "#fff", border: "1px solid #fca5a5", borderRadius: 8, padding: 16, overflow: "auto", fontSize: 12, color: "#991b1b", whiteSpace: "pre-wrap" }}>
              {String(this.state.error)}{"\n\n"}{this.state.error?.stack}
            </pre>
            <button onClick={() => window.location.reload()}
                    style={{ marginTop: 16, padding: "10px 24px", background: "#e11d48", color: "#fff", border: "none", borderRadius: 8, cursor: "pointer", fontSize: 14 }}>
              Reload page
            </button>
          </div>
        </div>
      );
    }
    return this.props.children;
  }
}

const ROLES = {
  Admin:   { perms: new Set(["view_all","create","approve","manage_users","manage_master","edit_all","attach_po","setup_groups"]) },
  Manager: { perms: new Set(["view_all","create","approve","manage_master","edit_all","attach_po"]) },
  User:    { perms: new Set(["view_own","create","attach_po","edit_own"]) },
};

const NAV_BY_ROLE = {
  User: [
    { group: "การทำงาน" },
    { id: "new",             label: "New Registration",  icon: "plus" },
    { id: "customer-update", label: "Customer Update",   icon: "edit" },
    { id: "registrations",   label: "ARS Registrations", icon: "list" },
    { id: "certificates",    label: "Certificates",      icon: "cert" },
  ],
  Manager: [
    { group: "การทำงาน" },
    { id: "dashboard",       label: "Dashboard",         icon: "dashboard" },
    { id: "registrations",   label: "ARS Registrations", icon: "list" },
    { id: "new",             label: "New Registration",  icon: "plus" },
    { id: "customer-update", label: "Customer Update",   icon: "edit" },
    { id: "approvals",       label: "Approvals",         icon: "approve", requires: ["approve"] },
    { id: "certificates",    label: "Certificates",      icon: "cert" },
    { group: "การตั้งค่า" },
    { id: "master",          label: "Master Data",       icon: "database", requires: ["manage_master"] },
    { id: "settings",        label: "Settings",          icon: "settings" },
  ],
  Admin: [
    { group: "การทำงาน" },
    { id: "dashboard",       label: "Dashboard",         icon: "dashboard" },
    { id: "registrations",   label: "ARS Registrations", icon: "list" },
    { id: "new",             label: "New Registration",  icon: "plus" },
    { id: "customer-update", label: "Customer Update",   icon: "edit" },
    { id: "approvals",       label: "Approvals",         icon: "approve", requires: ["approve"] },
    { id: "certificates",    label: "Certificates",      icon: "cert" },
    { group: "การตั้งค่า" },
    { id: "master",          label: "Master Data",       icon: "database", requires: ["manage_master"] },
    { id: "users",           label: "Users & Groups",    icon: "users",    requires: ["manage_users"] },
    { id: "settings",        label: "Settings",          icon: "settings" },
  ],
};

const SCREEN_LABELS = {
  dashboard: "Dashboard", registrations: "ARS Registrations",
  new: "New Registration", "customer-update": "Customer Update",
  approvals: "Approvals", certificates: "Certificates",
  master: "Master Data", users: "Users & Groups", settings: "Settings",
};

const DEFAULT_SCREEN = { Admin: "dashboard", Manager: "dashboard", User: "new" };

// Kept for screens that still reference it
window.USER_BY_ROLE = {
  Admin:   { name: "K. Wattana M.", title: "Service Admin",    initials: "WM" },
  Manager: { name: "K. Nattaya P.", title: "Service Manager",  initials: "NP" },
  User:    { name: "Pim S.",        title: "Sales — BKK",      initials: "PS" },
};

// ─── Loading splash ──────────────────────────────────────────────
function Splash({ text }) {
  return (
    <div style={{ minHeight: '100vh', background: 'var(--surface-2)', display: 'grid', placeItems: 'center' }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ fontSize: 36, fontFamily: 'var(--font-display)', fontWeight: 700, color: 'var(--jt-navy-800)' }}>JT</div>
        <div style={{ marginTop: 10, color: 'var(--text-muted)', fontSize: 14 }}>{text}</div>
      </div>
    </div>
  );
}

// ─── Main App ────────────────────────────────────────────────────
function App() {
  const [authUser,             setAuthUser]             = useState(null);
  const [profile,              setProfile]              = useState(null);
  const [profileLoaded,        setProfileLoaded]        = useState(false);
  const [authLoading,          setAuthLoading]          = useState(true);
  const [dataLoading,          setDataLoading]          = useState(false);
  const [passwordRecoveryMode, setPasswordRecoveryMode] = useState(false);

  // Ref: track whether we've set the initial screen already.
  // Prevents token-refresh / repeated onAuthStateChange calls from resetting
  // the screen mid-form. Initialised to true if we have a persisted screen
  // (so a remount doesn't overwrite the user's current location).
  const screenInitialised = React.useRef(
    (() => { try { return !!sessionStorage.getItem('ars_screen'); } catch (e) { return false; } })()
  );

  const [role,          setRole]          = useState("Admin");
  // Persist screen in sessionStorage so it survives any remount/refresh.
  // This is a defensive layer — if something causes App to unmount mid-form,
  // the user lands back on the screen they were last on, not "dashboard".
  const [screen, setScreen] = useState(() => {
    try { return sessionStorage.getItem('ars_screen') || 'dashboard'; }
    catch (e) { return 'dashboard'; }
  });
  useEffect(() => {
    try { sessionStorage.setItem('ars_screen', screen); } catch (e) {}
  }, [screen]);
  const [selectedId,    setSelectedId]    = useState(null);
  const [registrations, setRegistrations] = useState([]);
  const [packages,      setPackages]      = useState((window.ARS_DATA && window.ARS_DATA.PACKAGES) || []);
  const [appUsers,      setAppUsers]      = useState((window.ARS_DATA?.USERS  || []).map(u => ({ ...u, status: u.status || "active" })));
  const [appGroups,     setAppGroups]     = useState((window.ARS_DATA?.GROUPS || []).map(g => ({ ...g, status: g.status || "active" })));

  // ── Auth listener ──────────────────────────────────────────────
  useEffect(() => {
    // Safety net: force-unblock UI after 6 s in case auth never fires
    const safetyTimer = setTimeout(() => setAuthLoading(false), 6000);

    const { data: { subscription } } = window.sb.auth.onAuthStateChange(
      async (_event, session) => {
        clearTimeout(safetyTimer);
        if (session?.user) {
          // PASSWORD_RECOVERY event = user clicked "ลืมรหัสผ่าน" link
          if (_event === 'PASSWORD_RECOVERY') setPasswordRecoveryMode(true);

          // Clear URL hash if Supabase left it behind (cosmetic)
          if (window.location.hash) {
            window.history.replaceState(null, '', window.location.pathname);
          }

          setAuthUser(session.user);
          setAuthLoading(false);
          loadProfile(session.user.id);   // profile.password_set is the source of truth
          loadData();
        } else {
          // Clear persisted screen and wizard state on logout
          try {
            sessionStorage.removeItem('ars_screen');
            sessionStorage.removeItem('ars_wizard');
          } catch (e) {}
          screenInitialised.current = false;   // reset so next login sets screen again
          setAuthUser(null);
          setProfile(null);
          setProfileLoaded(false);
          setPasswordRecoveryMode(false);
          setRegistrations([]);
          setAuthLoading(false);
        }
      }
    );
    return () => { clearTimeout(safetyTimer); subscription.unsubscribe(); };
  }, []);

  const loadProfile = async (uid) => {
    try {
      // Race: give up after 6 s so a network hang never blocks anything
      const { data } = await Promise.race([
        window.sb.from('profiles').select('*').eq('id', uid).maybeSingle(),
        new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), 6000)),
      ]);
      if (data) {
        setProfile(data);
        const r = ROLES[data.role] ? data.role : 'User';
        setRole(r);
        // Only set the initial screen once — do NOT reset on token-refresh / re-auth
        if (!screenInitialised.current) {
          screenInitialised.current = true;
          setScreen(DEFAULT_SCREEN[r] || 'new');
        }
      }
    } catch (e) {
      console.warn('loadProfile (non-fatal):', e.message);
    } finally {
      setProfileLoaded(true);   // mark done so UI can advance past splash
    }
  };

  const loadData = async () => {
    setDataLoading(true);
    try {
      const [{ data: regs }, { data: pkgs }, { data: profiles }] = await Promise.all([
        window.sb.from('ars_registrations').select('*').order('created_at', { ascending: false }),
        window.sb.from('warranty_packages').select('*').order('code'),
        window.sb.from('profiles').select('*').order('created_at', { ascending: true }),
      ]);
      if (regs)                   setRegistrations(regs.map(window.rowToReg));
      if (pkgs && pkgs.length)    setPackages(pkgs.map(p => ({ ...p, price: Number(p.price) || 0 })));
      if (profiles && profiles.length) setAppUsers(profiles.map(window.rowToUser));
    } catch (e) {
      console.error('Data load error:', e);
    }
    setDataLoading(false);
  };

  const logout = async () => {
    await window.sb.auth.signOut();
  };

  // ── Role change guard (DISABLED — loadProfile sets the initial screen once;
  //     auto-resets here were causing the wizard to bounce to dashboard mid-form
  //     whenever Supabase ran a token refresh or fired a re-auth event.) ───

  // ── Tweaks (inline — never conditional, hooks rules require consistent call order)
  const TWEAK_DEFAULTS = { accent: "#e11d48", density: "comfortable", showActivity: true, showWelcome: true };
  const [t, _setTState] = useState(TWEAK_DEFAULTS);
  const setTweak = React.useCallback((k, v) => {
    const edits = (typeof k === 'object' && k !== null) ? k : { [k]: v };
    _setTState(prev => ({ ...prev, ...edits }));
  }, []);

  useEffect(() => {
    document.documentElement.style.setProperty("--jt-red", t.accent);
  }, [t.accent]);

  // ── Counts (useMemo MUST be before any early returns — hooks rules)
  const counts = useMemo(() => ({
    pending: registrations.filter(r => r.status === "pending_approval").length,
    draft:   registrations.filter(r => r.status === "draft").length,
    total:   registrations.length,
  }), [registrations]);

  // ── Guards ────────────────────────────────────────────────────
  if (authLoading)    return <Splash text="กำลังตรวจสอบสิทธิ์…" />;
  if (!authUser)      return <LoginScreen onLogin={() => {}} />;
  if (!profileLoaded) return <Splash text="กำลังโหลดโปรไฟล์…" />;

  // SetPasswordScreen: ทุก user ที่ยังไม่ได้ตั้ง password (profile.password_set=false)
  //                    หรือเพิ่งคลิกลิงก์ "ลืมรหัสผ่าน"
  if (passwordRecoveryMode || profile?.password_set === false) {
    return (
      <SetPasswordScreen
        userId={authUser.id}
        onDone={() => {
          setPasswordRecoveryMode(false);
          loadProfile(authUser.id);   // re-fetch so password_set=true reflects in UI
        }}
      />
    );
  }
  // dataLoading: ไม่บล็อก UI — data โหลดใน background, screens แสดง empty state ระหว่างรอ

  // ── Derived state ─────────────────────────────────────────────
  const perms = (ROLES[role] || ROLES["User"]).perms;
  const can = (p) => perms.has(p);

  const go = (id, sel = null) => { setScreen(id); setSelectedId(sel); window.scrollTo(0, 0); };

  const navItems = (NAV_BY_ROLE[role] || []).filter(
    item => !item.requires || item.requires.some(p => can(p))
  );

  // Current user display.
  // Show role as the secondary label — it's the most accurate truth (matches
  // Users & Groups page) and avoids confusion when profile.title is stale or
  // mismatched (e.g. a User whose title was accidentally set to "admin").
  //
  // cleanName strips invisible / weird leading symbols (e.g. U+2021 "‡",
  // zero-width chars, BOM) that sometimes slip into profile.name through
  // copy-paste. Keeps letters (any script incl. Thai), digits, and spaces.
  const cleanName = (s) => (s || '').replace(/^[^\p{L}\p{N}]+/u, '').trim();
  const rawName      = profile?.name || authUser?.email?.split('@')[0] || 'User';
  const displayName  = cleanName(rawName) || rawName;
  const displayTitle = role || 'User';
  const initials     = displayName.split(/\s+/).map(p => p[0]).slice(0, 2).join('').toUpperCase() || '?';

  const currentUser = { name: displayName, title: displayTitle, initials, email: authUser.email, role };

  const ctx = {
    role, can, registrations, setRegistrations, go, selectedId, setSelectedId,
    t, setTweak, packages, setPackages, currentUser,
    appUsers, setAppUsers, appGroups, setAppGroups,
  };

  return (
    <ErrorBoundary>
    <div className="app">
      {/* ── Sidebar ── */}
      <aside className="sidebar">
        <div className="sidebar__brand">
          <div className="sidebar__brand-mark">JT</div>
          <div className="sidebar__brand-text">
            <strong>JOURNEY TECH</strong>
            <span>ARS Service Management</span>
          </div>
        </div>
        <nav className="sidebar__nav">
          {navItems.map((item, i) => {
            if (item.group) return <div key={"g"+i} className="sidebar__group">{item.group}</div>;
            const badge = item.id === "approvals"     ? counts.pending
                        : item.id === "registrations" ? counts.total
                        : null;
            return (
              <div key={item.id}
                   className={"sidebar__item " + (screen === item.id ? "is-active" : "")}
                   onClick={() => go(item.id)}>
                <Icon name={item.icon} />
                <span>{item.label}</span>
                {badge > 0 && <span className="count">{badge}</span>}
              </div>
            );
          })}
        </nav>
        <div className="sidebar__user">
          <div className="sidebar__avatar">{initials}</div>
          <div className="sidebar__user-info">
            <strong>{displayName}</strong>
            <span>{displayTitle}</span>
          </div>
          <button onClick={logout} title="Logout"
                  style={{ marginLeft: 'auto', background: 'none', border: 'none',
                           cursor: 'pointer', color: 'rgba(255,255,255,0.45)', padding: 6 }}>
            <Icon name="x" size={14}/>
          </button>
        </div>
      </aside>

      {/* ── Main ── */}
      <div className="main">
        <div className="topbar">
          <div className="topbar__crumbs">
            <span>Service Management</span>
            <Icon name="chevron-right" size={14}/>
            <strong>{SCREEN_LABELS[screen]}</strong>
          </div>
          <div className="topbar__search">
            <Icon name="search" size={16}/>
            <input placeholder="ค้นหา ARS no., PO, ลูกค้า, S/N…"/>
            <kbd>⌘K</kbd>
          </div>
          <div className="topbar__icon"><Icon name="bell" size={18}/><span className="dot"></span></div>
        </div>

        {screen === "dashboard"       && <Dashboard ctx={ctx}/>}
        {screen === "registrations"   && (selectedId ? <RegistrationDetail ctx={ctx}/> : <RegistrationsList ctx={ctx}/>)}
        {screen === "new"             && <NewRegistrationWizard ctx={ctx}/>}
        {screen === "customer-update" && <CustomerUpdateScreen ctx={ctx}/>}
        {screen === "approvals"       && <ApprovalQueue ctx={ctx}/>}
        {screen === "certificates"    && <CertificatesScreen ctx={ctx}/>}
        {screen === "master"          && <MasterData ctx={ctx}/>}
        {screen === "users"           && <UsersAndGroups ctx={ctx}/>}
        {screen === "settings"        && <Settings ctx={ctx}/>}
      </div>

      {window.TweaksPanel && (
        <TweaksPanel title="Tweaks">
          <TweakSection title="Theme">
            <TweakColor label="Accent (Journey Red)" value={t.accent} onChange={v => setTweak('accent', v)}
              options={["#e11d48","#dc2626","#0f2a6b","#7c3aed","#0d9488"]}/>
          </TweakSection>
          <TweakSection title="Layout">
            <TweakRadio label="Density" value={t.density} onChange={v => setTweak('density', v)}
              options={[{value:"comfortable",label:"Comfortable"},{value:"compact",label:"Compact"}]}/>
            <TweakToggle label="Recent activity panel" value={t.showActivity} onChange={v => setTweak('showActivity', v)}/>
            <TweakToggle label="Welcome banner"        value={t.showWelcome}  onChange={v => setTweak('showWelcome', v)}/>
          </TweakSection>
        </TweaksPanel>
      )}
    </div>
    </ErrorBoundary>
  );
}

window.App = App;
window.ErrorBoundary = ErrorBoundary;
