// main.jsx — App root: hoists state, provides PortalContext, routes, mounts.
function App() {
  const [lang, setLang] = usePersist('lang', 'vi');
  return (
    <ToastProvider>
      <LangProvider lang={lang} setLang={setLang}>
        <PortalApp />
      </LangProvider>
    </ToastProvider>
  );
}

function PortalApp() {
  const { t, tt, lang } = useLang();
  const toast = useToast();

  const [session, setSession] = React.useState(null);
  const [booted, setBooted] = React.useState(!window.SB_READY);   // đã kiểm tra phiên ban đầu chưa
  const [profile, setProfile] = React.useState(null);   // hồ sơ user thật (khi đăng nhập)
  const authed = !!session;                     // BẮT BUỘC đăng nhập Supabase (đã bỏ demo)
  const [route, setRoute] = React.useState({ name:'dashboard' });
  const [role, setRole] = usePersist('role', 'staff');
  const [pinned, setPinned] = usePersist('pinnedv2', ['mail', 'customers', 'contacts', 'contracts', 'finance']);
  const [hidden, setHidden] = usePersist('hidden', []);
  const [density, setDensity] = usePersist('density', 'comfortable');
  const [fontsize, setFontsize] = usePersist('fontsize', 'md');
  const [collapsed, setCollapsed] = usePersist('collapsed', false);
  const [drawerOpen, setDrawerOpen] = React.useState(false);

  const [customers, setCustomers] = React.useState(CUSTOMERS);
  const [contacts, setContacts] = React.useState(CONTACTS);
  const [sentEmails, setSentEmails] = React.useState(SENT_EMAILS);
  const [templates, setTemplates] = React.useState(EMAIL_TEMPLATES);
  const [mailSettings, setMailSettings] = React.useState({ signature:SIGNATURE, account:'no-reply@swo.vn', connected:true });
  const [users, setUsers] = React.useState(Object.values(USERS));   // demo: persona mock; đăng nhập: user thật từ profiles
  const [contracts, setContracts] = React.useState(CONTRACTS);
  const [expenses, setExpenses] = React.useState(EXPENSES);
  const [pendingData, setPendingData] = React.useState({ mail:null });

  const [cmdkOpen, setCmdkOpen] = React.useState(false);
  const [newCustomerOpen, setNewCustomerOpen] = React.useState(false);
  const [newContactOpen, setNewContactOpen] = React.useState(false);
  const [newContractOpen, setNewContractOpen] = React.useState(false);

  /* apply appearance to <html> */
  React.useEffect(() => { document.documentElement.dataset.density = density; }, [density]);
  React.useEffect(() => { document.documentElement.dataset.fontsize = fontsize; }, [fontsize]);

  /* ⌘K */
  React.useEffect(() => {
    const h = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); setCmdkOpen(o => !o); }
    };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, []);

  /* Supabase auth: theo dõi phiên */
  React.useEffect(() => {
    if (!window.SB_READY) return;
    sb.auth.getSession().then(({ data }) => { setSession(data.session || null); setBooted(true); });
    const { data:sub } = sb.auth.onAuthStateChange((_e, s) => setSession(s || null));
    return () => sub.subscription.unsubscribe();
  }, []);

  /* Có phiên → nạp dữ liệu thật (thay mock) + role từ profiles. Không phiên (demo) → giữ mock. */
  React.useEffect(() => {
    let alive = true;
    if (session && window.SB_READY) {
      DB.loadAll().then(d => {
        if (!alive || !d) return;
        setCustomers(d.customers); setContacts(d.contacts);
        setContracts(d.contracts); setExpenses(d.expenses);
        if (d.templates) setTemplates(d.templates);
        if (d.sentEmails) setSentEmails(d.sentEmails);
        if (d.mailSettings) setMailSettings(d.mailSettings);
      });
      DB.myProfile(session.user.id).then(pr => { if (alive && pr) { setProfile(pr); if (pr.role) setRole(pr.role); } });
      DB.listUsers().then(us => { if (alive && us && us.length) setUsers(us); });
    } else if (!session) {
      setProfile(null);
    }
    return () => { alive = false; };
  }, [session]);

  /* optimistic persist: ghi nền khi đã đăng nhập; lỗi → toast + rollback. Demo → chỉ in-memory. */
  const persist = (fn, rollback) => {
    if (!(window.SB_READY && session)) return;
    Promise.resolve().then(fn).catch(e => {
      console.warn('[persist]', e && e.message);
      toast(lang === 'vi' ? 'Lưu lên máy chủ thất bại' : 'Failed to save to server', 'error');
      if (rollback) rollback();
    });
  };

  /* expose query stores synchronously (ready before children first render) */
  window.CustomerStore = {
    all:() => customers,
    byCode:(code) => customers.find(c => c.code === code),
    byId:(code) => customers.find(c => c.code === code),
    search:(q) => customers.filter(c => (c.name + c.code + c.shortName).toLowerCase().includes((q || '').toLowerCase())),
    codes:() => customers.map(c => c.code),
  };
  window.ContactStore = {
    all:() => contacts,
    byCode:(code) => contacts.find(c => c.code === code),
    byId:(code) => contacts.find(c => c.code === code),
    byCustomer:(code) => contacts.filter(c => c.customer === code),
    search:(q) => contacts.filter(c => (c.name + c.code + c.email).toLowerCase().includes((q || '').toLowerCase())),
    codes:() => contacts.map(c => c.code),
  };
  window.ContractStore = {
    all:() => contracts,
    byCode:(code) => contracts.find(c => c.code === code),
    byCustomer:(code) => contracts.filter(c => c.customer === code),
    totalValue:() => contracts.reduce((s, c) => s + contractTotals(c).total, 0),
    codes:() => contracts.map(c => c.code),
  };

  const apps = APPS.filter(a => !hidden.includes(a.id) && (!a.adminOnly || role === 'admin'));
  // danh tính: user thật khi đăng nhập (giữ role hiện hành để switcher vẫn preview được quyền), mock khi demo
  const me = profile ? { id:profile.id, name:profile.name, email:profile.email, title:profile.title || USERS[role].title, role } : USERS[role];

  const navigate = (r) => { setRoute(r); setDrawerOpen(false); document.querySelector('.main') && document.querySelector('.main').scrollTo(0, 0); };
  const openApp = (app) => {
    if (app.module) navigate({ name:'module', module:app.module });
    else toast(t('apps.noModule'), 'info');
  };
  const quick = (mod, data) => {
    if (mod === 'mail') { setPendingData(d => ({ ...d, mail:data || {} })); navigate({ name:'module', module:'mail', sub:'compose' }); }
    else if (mod === 'customers') setNewCustomerOpen(true);
    else if (mod === 'contacts') setNewContactOpen(true);
    else if (mod === 'contracts') setNewContractOpen(true);
  };
  const togglePin = (id) => setPinned(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const toggleHidden = (id) => setHidden(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);

  const portal = {
    route, navigate, role, setRole, me, users, apps, lang, t, tt, toast,
    pinned, togglePin, hidden, toggleHidden,
    customers, contacts, sentEmails,
    addCustomer:(c) => { setCustomers(s => [c, ...s]); persist(() => DB.insertCustomer(c), () => setCustomers(s => s.filter(x => x !== c))); },
    updateCustomer:(code, next) => { const prev = customers.find(c => c.code === code); setCustomers(s => s.map(c => c.code === code ? next : c)); persist(() => DB.updateCustomer(next), () => prev && setCustomers(s => s.map(c => c.code === code ? prev : c))); },
    deleteCustomer:(code) => { const prev = customers; setCustomers(s => s.filter(c => c.code !== code)); persist(() => DB.deleteCustomer(code), () => setCustomers(prev)); },
    addContact:(c) => { setContacts(s => [c, ...s]); persist(() => DB.insertContact(c), () => setContacts(s => s.filter(x => x !== c))); },
    updateContact:(code, next) => { const prev = contacts.find(c => c.code === code); setContacts(s => s.map(c => c.code === code ? next : c)); persist(() => DB.updateContact(next), () => prev && setContacts(s => s.map(c => c.code === code ? prev : c))); },
    deleteContact:(code) => { const prev = contacts; setContacts(s => s.filter(c => c.code !== code)); persist(() => DB.deleteContact(code), () => setContacts(prev)); },
    addSentEmail:(e) => { setSentEmails(s => [e, ...s]); persist(() => DB.insertSentEmail(e), () => setSentEmails(s => s.filter(x => x !== e))); },
    templates, mailSettings,
    updateTemplate:(tpl) => {
      const prev = templates.find(x => x.id === tpl.id);
      setTemplates(s => s.map(x => x.id === tpl.id ? tpl : x));
      persist(() => DB.upsertTemplate(tpl), () => prev && setTemplates(s => s.map(x => x.id === tpl.id ? prev : x)));
    },
    saveMailSettings:(patch) => {
      const prev = mailSettings, next = { ...mailSettings, ...patch };
      setMailSettings(next);
      persist(() => DB.saveSettings(next), () => setMailSettings(prev));
    },
    contracts, expenses,
    saveContract:(c) => { setContracts(s => [c, ...s]); persist(() => DB.upsertContract(c), () => setContracts(s => s.filter(x => x !== c))); },
    patchContract:(code, next) => {
      const prev = contracts.find(c => c.code === code);
      setContracts(s => s.map(c => c.code === code ? next : c));
      persist(() => DB.upsertContract(next), () => prev && setContracts(s => s.map(c => c.code === code ? prev : c)));
    },
    deleteContract:(code) => { const prev = contracts; setContracts(s => s.filter(c => c.code !== code)); persist(() => DB.deleteContract(code), () => setContracts(prev)); },
    addExpense:(e) => { setExpenses(s => [e, ...s]); persist(() => DB.insertExpense(e), () => setExpenses(s => s.filter(x => x !== e))); },
    updateExpense:(id, next) => { const prev = expenses.find(e => e.id === id); setExpenses(s => s.map(e => e.id === id ? next : e)); persist(() => DB.updateExpense(next), () => prev && setExpenses(s => s.map(e => e.id === id ? prev : e))); },
    deleteExpense:(id) => { const prev = expenses; setExpenses(s => s.filter(e => e.id !== id)); persist(() => DB.deleteExpense(id), () => setExpenses(prev)); },
    quick, openApp, openCmdk:() => setCmdkOpen(true),
    density, setDensity, fontsize, setFontsize, collapsed, setCollapsed, drawerOpen, setDrawerOpen,
    pendingData, clearPending:() => setPendingData(d => ({ ...d, mail:null })),
    logout:() => { if (window.SB_READY) sb.auth.signOut(); navigate({ name:'dashboard' }); },
  };

  if (!booted) return null;   // chờ kiểm tra phiên xong, tránh nháy màn login khi đã đăng nhập
  if (!authed) return <Login onLogin={() => { if (window.SB_READY) sb.auth.getSession().then(({ data }) => setSession(data.session || null)); }} />;

  const portalPages = {
    dashboard:Dashboard, allapps:AllApps, admin:AdminConsole,
    tasks:TasksPage, approvals:ApprovalsPage, notifs:NotifsPage, settings:SettingsPage,
  };

  let body;
  if (route.name === 'module') {
    body = route.module === 'mail' ? <MailModule />
      : route.module === 'customers' ? <CustomerModule />
      : route.module === 'contacts' ? <ContactModule />
      : route.module === 'contracts' ? <ContractModule />
      : route.module === 'finance' ? <FinanceModule />
      : <div className="main"><EmptyState text={t('c.empty')} /></div>;
  } else {
    const Page = portalPages[route.name] || Dashboard;
    body = <><PortalSidebar /><main className="main"><Page /></main></>;
  }

  return (
    <PortalContext.Provider value={portal}>
      <div className={'shell' + (collapsed ? ' collapsed' : '') + (drawerOpen ? ' drawer-open' : '')}>
        <Brandbar />
        <Topbar />
        {body}
      </div>
      {drawerOpen && <div className="drawer-scrim" onClick={() => setDrawerOpen(false)}></div>}
      {route.name === 'module' && <PortalFAB />}
      {cmdkOpen && <CommandPalette onClose={() => setCmdkOpen(false)} />}
      {newCustomerOpen && <NewCustomerModal onClose={() => setNewCustomerOpen(false)} />}
      {newContactOpen && <NewContactModal onClose={() => setNewContactOpen(false)} />}
      {newContractOpen && <NewContractModal onClose={() => setNewContractOpen(false)} />}
    </PortalContext.Provider>
  );
}

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