// ============ Main App — API-connected ============

// ---- Auth screen ----
function AuthScreen({ error }) {
  return (
    <div className="auth-screen">
      <div className="auth-card">
        <div className="auth-logo">
          <img src="/email-agent-icon.png" alt="ATLAS Email Agent" style={{width:80,height:80,borderRadius:'50%',objectFit:'cover'}} />
        </div>
        <h1>ATLAS Email Agent</h1>
        <p>AI-powered inbox management for Elite Roads.<br/>Connect your Microsoft 365 account to get started.</p>
        {error && <div className="auth-error">{error}</div>}
        <a href="/auth/login" className="btn primary auth-btn">
          <I.ms365/> Sign in with Microsoft 365
        </a>
        <div className="auth-note">
          Sign in with your Elite Roads Microsoft 365 account to get started.
        </div>
      </div>
    </div>
  );
}

// ---- Mailbox Switcher ----
function MailboxSwitcher({ activeMailbox, mailboxes, onSwitch }) {
  const [open, setOpen] = useState(false);
  const current = mailboxes.find(m => m.id === activeMailbox) || mailboxes[0];
  const isShared = activeMailbox === 'shared:tenders';

  return (
    <div style={{position:'relative', padding:'0 8px 8px', borderBottom:'1px solid var(--line)', marginBottom:4}}>
      <button
        onClick={() => setOpen(o => !o)}
        style={{
          all:'unset', display:'flex', alignItems:'center', gap:8, width:'100%',
          padding:'7px 8px', borderRadius:'var(--radius-sm)',
          cursor:'pointer', fontSize:12, color:'var(--ink-2)',
          background: open ? 'var(--bg-3)' : 'transparent',
        }}
        onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-3)'}
        onMouseLeave={e => e.currentTarget.style.background = open ? 'var(--bg-3)' : 'transparent'}
      >
        <span style={{fontSize:14, flexShrink:0}}>{current?.icon}</span>
        <span style={{flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap'}}>
          {current?.name || 'My Inbox'}
        </span>
        {isShared && (
          <span style={{
            fontSize:9, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.06em',
            background:'#d97706', color:'#fff', padding:'1px 5px', borderRadius:3, flexShrink:0,
          }}>Shared</span>
        )}
        <span style={{color:'var(--ink-4)', fontSize:10, flexShrink:0}}>{open ? '▲' : '▼'}</span>
      </button>
      {open && (
        <div style={{
          position:'absolute', left:8, right:8, top:'100%', marginTop:2, zIndex:100,
          background:'var(--bg)', border:'1px solid var(--line)', borderRadius:8,
          boxShadow:'0 4px 16px rgba(0,0,0,.12)', overflow:'hidden',
        }}>
          {mailboxes.map(mb => (
            <button key={mb.id}
              onClick={() => { onSwitch(mb.id); setOpen(false); }}
              style={{
                all:'unset', display:'flex', alignItems:'center', gap:8,
                width:'100%', padding:'9px 12px', cursor:'pointer', fontSize:12,
                background: mb.id === activeMailbox ? 'var(--bg-2)' : 'transparent',
                borderBottom:'1px solid var(--line)',
                boxSizing:'border-box',
              }}
              onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-3)'}
              onMouseLeave={e => e.currentTarget.style.background = mb.id === activeMailbox ? 'var(--bg-2)' : 'transparent'}
            >
              <span style={{fontSize:14}}>{mb.icon}</span>
              <div style={{flex:1, minWidth:0}}>
                <div style={{fontWeight:600, color:'var(--ink)', fontSize:12}}>{mb.name}</div>
                <div style={{color:'var(--ink-3)', fontSize:11, marginTop:1}}>{mb.email}</div>
              </div>
              {mb.id === activeMailbox && <span style={{color:'var(--accent)', fontSize:12}}>✓</span>}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// ---- Sidebar ----
function Sidebar({ view, setView, counts, employee, profile, activeMailbox, mailboxes, onMailboxSwitch }) {
  const isFleet   = profile?.interface === 'fleet';
  const isQuoting = activeMailbox === 'shared:tenders';
  const nav = [
    // Personal inbox items — only shown when on personal mailbox (not tenders@)
    ...(!isQuoting ? [
      { key:'todo',     label:'To-do list',        icon:<I.inbox/>,    count:counts.todo,     section:'Inbox' },
      { key:'done',     label:'Done',              icon:<I.check/>,    count:counts.done },
      { key:'deleted',  label:'Recently Deleted',  icon:<I.trash/>,    count:counts.deleted||undefined },
      { key:'followup', label:'Follow-ups',        icon:<I.clock/>,    count:counts.followup, urgent:counts.followup>0, section:'Watching' },
      { key:'disputes', label:'Disputes & claims', icon:<I.gavel/>,    count:counts.disputes, urgent:counts.disputesEsc>0 },
    ] : []),
    ...(isFleet   ? [{ key:'fleet-kb',       label:'Fleet Intelligence', icon:<I.inbox/>,   section:'Fleet' }]   : []),
    ...(isQuoting ? [
      { key:'tenders-inbox',    label:'Tenders Inbox',   icon:'📋',  count:counts.tenderUnread||undefined, section:'Quoting' },
      { key:'opportunities',    label:'Opportunities',   icon:'🎯',  count:counts.opportunitiesNew||undefined, urgent:counts.opportunitiesNew>0 },
      { key:'move-log',         label:'Move Log',        icon:'📂',  section:'' },
      { key:'followup',         label:'Follow-ups',      icon:<I.clock/>, count:counts.followup, urgent:counts.followup>0 },
    ] : []),
    { key:'folders',  label:'Folder rules',      icon:<I.folder/>,   section:'Configuration' },
    { key:'style',    label:'Settings',          icon:<I.settings/> },
  ];

  const initials = (employee?.name || 'U').split(' ').map(w=>w[0]).slice(0,2).join('').toUpperCase();

  return (
    <aside className="sidebar">
      <div className="brand">
        <img src="/email-agent-icon.png" alt="" style={{width:36,height:36,borderRadius:'50%',objectFit:'cover',flexShrink:0}} />
        <div>
          <div className="brand-name">ATLAS Email Agent</div>
          <div className="brand-sub">elite-roads · v2.0</div>
        </div>
      </div>
      {mailboxes.length > 1 && (
        <MailboxSwitcher
          activeMailbox={activeMailbox}
          mailboxes={mailboxes}
          onSwitch={onMailboxSwitch}
        />
      )}
      {nav.map(n => (
        <React.Fragment key={n.key}>
          {n.section && <div className="nav-section-label">{n.section}</div>}
          <button className="nav-item" aria-current={view===n.key ? 'page' : undefined} onClick={() => setView(n.key)}>
            <span className="nav-icon">{typeof n.icon === 'string' ? n.icon : n.icon}</span>
            <span className="nav-label">{n.label}</span>
            {n.count != null && <span className={`nav-count ${n.urgent ? 'urgent' : ''}`}>{n.count}</span>}
          </button>
        </React.Fragment>
      ))}
      <div className="sidebar-foot">
        <div className="user-row">
          <div className="avatar">{initials}</div>
          <div style={{minWidth:0}}>
            <div className="user-name">{employee?.name || 'User'}</div>
            <div className="user-email" style={{whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>
              {employee?.email || ''}
            </div>
          </div>
        </div>
        <button className="btn ghost sm" style={{marginTop:8, width:'100%', fontWeight:600, fontSize:11.5,
            background:'rgba(37,99,235,0.08)', borderColor:'rgba(37,99,235,0.3)', color:'#2563eb'}}
          onClick={() => { window.location.href = '/auth/switch'; }}>
          🔄 Switch account
        </button>
        <button className="btn ghost sm" style={{marginTop:4, width:'100%', fontSize:10.5, opacity:0.55}}
          onClick={async () => { await api.post('/api/auth/logout', {}); location.reload(); }}>
          Sign out
        </button>
      </div>
    </aside>
  );
}

// ---- Topbar ----
function Topbar({ view, scanning, lastScan, nextScanAt, onScan, showRail, onToggleRail, onRefreshAll, refreshingAll }) {
  const titles = {
    todo:'To-do list', done:'Done', followup:'Follow-ups',
    disputes:'Disputes & claims', folders:'Folder rules', style:'Settings',
    'fleet-kb':'Fleet Intelligence', 'tenders-inbox':'Tenders Inbox', 'opportunities':'Opportunities', 'move-log':'Move Log',
  };
  const [now, setNow] = useState(Date.now());
  useEffect(() => { const t = setInterval(() => setNow(Date.now()), 10000); return () => clearInterval(t); }, []);
  const mins = lastScan ? Math.round((now - new Date(lastScan)) / 60000) : null;
  const nextMins = nextScanAt ? Math.max(0, Math.round((new Date(nextScanAt) - now) / 60000)) : null;
  return (
    <header className="topbar">
      <h1>
        <span className="crumb">ATLAS Email Agent &nbsp;/&nbsp; </span>{titles[view]}
      </h1>
      <div className="topbar-spacer"/>
      <div className="scan-chip">
        <span className={`scan-dot ${scanning ? 'scanning' : ''}`}/>
        {scanning
          ? <span>Scanning inbox…</span>
          : <>
              <span>Connected · M365</span>
              {mins !== null && <span className="mono">· last scan {mins}m ago</span>}
              {nextMins !== null && <span className="mono" style={{color:'#16a34a'}}>· next in {nextMins}m</span>}
            </>
        }
      </div>
      {/* Refresh All — reloads folders + emails + state in one click */}
      <button
        onClick={onRefreshAll}
        disabled={refreshingAll || scanning}
        title="Refresh everything — folders, emails, scan"
        style={{
          all:'unset', cursor: refreshingAll ? 'default' : 'pointer',
          display:'inline-flex', alignItems:'center', gap:6,
          padding:'6px 14px', borderRadius:7,
          background: refreshingAll ? '#f0ede8' : '#1a1a18',
          color: refreshingAll ? '#9ca3af' : '#fff',
          fontSize:12, fontWeight:700, border:'1px solid transparent',
          transition:'all 0.15s',
        }}
      >
        <span style={{ fontSize:14, display:'inline-block', animation: refreshingAll ? 'spin 0.8s linear infinite' : 'none' }}>↻</span>
        {refreshingAll ? 'Refreshing…' : 'Refresh All'}
      </button>
      <button className="btn" onClick={onScan} disabled={scanning} style={{ marginLeft:4 }}>
        {scanning ? <I.spin/> : <I.refresh/>} {scanning ? 'Scanning…' : 'Scan now'}
      </button>
      <button
        onClick={onToggleRail}
        title={showRail ? 'Hide agent panel' : 'Show agent panel'}
        className="btn ghost"
        style={{ marginLeft:4, fontSize:12, padding:'5px 9px', opacity: showRail ? 0.6 : 1 }}
      >{showRail ? '❮❮' : '❯❯'}</button>
    </header>
  );
}

// ---- Activity rail ----
function ActivityRail({ log, pipelineStep, stats, onCollapse }) {
  const steps = [
    'Fetch new emails',
    'Remove duplicates',
    'Classify & prioritise',
    'Group by thread',
    'Detect follow-ups',
    'Update to-do list',
  ];
  const logRef = useRef(null);
  useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight;
  }, [log]);

  return (
    <aside className="rail">
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:4 }}>
        <h3 style={{ margin:0 }}>Agent status</h3>
        <button
          onClick={onCollapse}
          title="Collapse panel"
          style={{ all:'unset', cursor:'pointer', fontSize:13, color:'var(--ink-4)', padding:'2px 6px',
            borderRadius:4, lineHeight:1, background:'var(--bg-2)', border:'1px solid var(--line)' }}
        >&#x276E;&#x276E;</button>
      </div>
      <div className="stat-row">
        <div className="stat"><div className="v">{stats?.scanned  || 0}</div><div className="l">Scanned</div></div>
        <div className="stat"><div className="v">{stats?.classified||0}</div><div className="l">Classified</div></div>
        <div className="stat"><div className="v">{stats?.moved    || 0}</div><div className="l">Moved</div></div>
      </div>

      <h3>Scan pipeline</h3>
      <div className="rail-card">
        <div className="pipeline">
          {steps.map((s, i) => {
            const status = pipelineStep > i ? 'done' : pipelineStep === i ? 'active' : 'idle';
            return (
              <div className={`pipe-step ${status}`} key={i}>
                <span className="n">{String(i+1).padStart(2,'0')}</span>
                <span className="label">{s}</span>
                <span className="status">{status==='done' ? '✓ ok' : status==='active' ? '…' : '—'}</span>
              </div>
            );
          })}
        </div>
      </div>

      <h3>Activity log</h3>
      <div className="rail-card">
        <div className="log" ref={logRef}>
          {(log || []).map((l,i) => (
            <div key={i}>
              <span className="ts">{l.t}</span>
              <span className={l.kind || ''}>{l.msg}</span>
            </div>
          ))}
        </div>
      </div>

      <h3>AI Usage</h3>
      <div className="rail-card" style={{fontSize:11.5, color:'var(--ink-2)', lineHeight:1.55}}>
        {[
          ['Tokens used',  (stats?.tokens||0).toLocaleString()],
          ['Emails per scan', '≤ 20'],
        ].map(([k,v]) => (
          <div key={k} style={{display:'flex', justifyContent:'space-between', color:'var(--ink-3)', marginTop:4}}>
            <span>{k}</span>
            <span style={{fontFamily:'var(--mono)'}}>{v}</span>
          </div>
        ))}
      </div>
    </aside>
  );
}

// ============ Root App ============
function App() {
  const [authStatus,   setAuthStatus]   = useState(null);   // null=loading, false=unauthed, true=authed
  const [authError,    setAuthError]    = useState(null);
  const [appState,     setAppState]     = useState(null);
  const [view,         setView]         = useState('todo');
  const [toasts,       setToasts]       = useState([]);
  const [openTask,     setOpenTask]     = useState(null);
  const [openThread,   setOpenThread]   = useState(null);
  const [banner,       setBanner]       = useState(null);
  const [showRail,     setShowRail]     = useState(false);
  const [refreshKey,   setRefreshKey]   = useState(0); // increment to force TenderView full reload
  const [refreshingAll, setRefreshingAll] = useState(false);
  const [activeMailbox, setActiveMailbox] = useState('me');
  const [mailboxes,     setMailboxes]     = useState([]);

  // ---- Auth check on mount ----
  useEffect(() => {
    // Read auth_error from URL if any
    const params = new URLSearchParams(location.search);
    if (params.get('auth_error')) {
      setAuthError(decodeURIComponent(params.get('auth_error')));
      history.replaceState({}, '', '/');
    }

    api.get('/api/auth/status')
      .then(({ authenticated }) => setAuthStatus(authenticated))
      .catch(() => setAuthStatus(false));
  }, []);

  // ---- Poll state when authenticated ----
  useEffect(() => {
    if (!authStatus) return;

    const load = () => {
      api.get('/api/state')
        .then(s => setAppState(s))
        .catch(console.error);
    };

    load();
    const id = setInterval(load, 20000); // refresh every 20 s
    return () => clearInterval(id);
  }, [authStatus]);

  // ---- Load mailboxes once authenticated ----
  useEffect(() => {
    if (!authStatus) return;
    api.get('/api/mailbox/list')
      .then(list => setMailboxes(list))
      .catch(() => {});
  }, [authStatus]);

  // ---- Restore activeMailbox from session on first state load ----
  const mailboxRestored = useRef(false);
  useEffect(() => {
    if (!appState || mailboxRestored.current) return;
    mailboxRestored.current = true;
    const mb = appState.activeMailbox || 'me';
    if (mb !== 'me') {
      setActiveMailbox(mb);
      if (mb === 'shared:tenders') setView('tenders-inbox');
    }
  }, [appState]);

  // ---- Mailbox switch ----
  const handleMailboxSwitch = useCallback(async (mailboxId) => {
    setActiveMailbox(mailboxId);
    try {
      await api.post('/api/mailbox/select', { mailbox: mailboxId });
    } catch (e) { /* non-critical */ }
    // Always switch to the correct interface view when mailbox changes
    if (mailboxId === 'shared:tenders') {
      setView('tenders-inbox');
    } else {
      setView('todo');
    }
  }, []);

  // ---- Helpers ----
  const pushToast = (msg, folder) => {
    const id = Math.random().toString(36).slice(2);
    setToasts(t => [...t, { id, msg, folder }]);
  };
  const removeToast = id => setToasts(t => t.filter(x => x.id !== id));

  const refreshState = useCallback(() => {
    api.get('/api/state').then(s => setAppState(s)).catch(console.error);
  }, []);

  // ---- Scan ----
  const handleScan = async () => {
    if (appState?.scanning) return;
    try {
      await api.post('/api/scan', {});
      pushToast('Scan started — refreshing shortly…');
      setTimeout(refreshState, 4000);
      setTimeout(refreshState, 9000);
    } catch (err) {
      pushToast('Scan failed: ' + err.message);
    }
  };

  // Register global handler so OpportunitiesView can jump back to Tenders Inbox
  useEffect(() => {
    window._jumpToConversation = (convId, subject) => {
      setView('tenders-inbox');
      setRefreshKey(k => k + 1);
      window._pendingConversationJump = { conversationId: convId, subject };
    };
    return () => { delete window._jumpToConversation; };
  }, []);

  // Refresh everything: state + tenders folder tree + current folder messages
  const handleRefreshAll = async () => {
    if (refreshingAll) return;
    setRefreshingAll(true);
    try {
      // 1. Bust folder tree cache + reload folders in-place (no remount)
      if (window._tenderBustRefresh) {
        await window._tenderBustRefresh();
      } else {
        setRefreshKey(k => k + 1); // fallback: full remount
      }
      // 2. Refresh app state
      refreshState();
      pushToast('↻ Refreshed — all folders and emails updated');
    } finally {
      setTimeout(() => setRefreshingAll(false), 3000);
    }
  };

  // ---- Thread toggle ----
  const handleToggle = (threadId) => {
    setAppState(prev => ({
      ...prev,
      threads: prev.threads.map(t => t.id === threadId ? { ...t, expanded: !t.expanded } : t),
    }));
  };

  // ---- Task done/undo ----
  const handleCheck = async (threadId, taskId) => {
    const thread = appState?.threads?.find(t => t.id === threadId);
    const task   = thread?.tasks?.find(t => t.id === taskId);
    if (!task) return;

    if (task.doneAt) {
      // undo
      await api.post('/api/task/undo', { threadId, taskId }).catch(console.error);
      setAppState(prev => ({
        ...prev,
        threads: prev.threads.map(th => th.id !== threadId ? th : {
          ...th, tasks: th.tasks.map(t => t.id !== taskId ? t : { ...t, doneAt: null }),
        }),
      }));
    } else {
      // optimistic update
      const now = new Date().toISOString();
      setAppState(prev => ({
        ...prev,
        threads: prev.threads.map(th => th.id !== threadId ? th : {
          ...th, tasks: th.tasks.map(t => t.id !== taskId ? t : { ...t, doneAt: now }),
        }),
      }));

      try {
        const { moved, folder } = await api.post('/api/task/done', { threadId, taskId });
        if (moved && folder) pushToast('Email moved in Outlook →', folder);

        // Task 5: auto-dismiss matching follow-ups
        const matchingFU = (appState?.followUps || []).filter(fu =>
          fu.threadId === threadId ||
          (fu.subject && task?.subject && fu.subject.toLowerCase() === task.subject.toLowerCase())
        );
        for (const fu of matchingFU) {
          api.post('/api/followup/dismiss', { id: fu.id }).catch(console.error);
        }

        refreshState();
      } catch (err) {
        // rollback
        setAppState(prev => ({
          ...prev,
          threads: prev.threads.map(th => th.id !== threadId ? th : {
            ...th, tasks: th.tasks.map(t => t.id !== taskId ? t : { ...t, doneAt: null }),
          }),
        }));
        pushToast('Error: ' + err.message);
      }
    }
  };

  // ---- Standalone task done/undo ----
  const handleCheckStandalone = async (taskId) => {
    const task = appState?.standaloneManualTasks?.find(t => t.id === taskId);
    if (!task) return;

    if (task.doneAt) {
      // undo
      setAppState(prev => ({
        ...prev,
        standaloneManualTasks: (prev.standaloneManualTasks || []).map(t =>
          t.id !== taskId ? t : { ...t, doneAt: null }
        ),
      }));
      api.post('/api/task/standalone/undo', { id: taskId }).catch(console.error);
    } else {
      // mark done
      const now = new Date().toISOString();
      setAppState(prev => ({
        ...prev,
        standaloneManualTasks: (prev.standaloneManualTasks || []).map(t =>
          t.id !== taskId ? t : { ...t, doneAt: now }
        ),
      }));
      try {
        await api.post('/api/task/standalone/done', { id: taskId });
        refreshState();
      } catch (err) {
        setAppState(prev => ({
          ...prev,
          standaloneManualTasks: (prev.standaloneManualTasks || []).map(t =>
            t.id !== taskId ? t : { ...t, doneAt: null }
          ),
        }));
        pushToast('Error: ' + err.message);
      }
    }
  };

  // ---- Dispute actions ----
  const handleDispute = async (a) => {
    try {
      if (a.type === 'state') {
        await api.post('/api/dispute/state', { id: a.id, state: a.next });
        if (a.next === 'resolved') pushToast('Email moved in Outlook →', 'Disputes & Claims');
      }
      if (a.type === 'close') {
        await api.post('/api/dispute/close', { id: a.id });
        pushToast('Dispute closed →', 'Disputes & Claims');
      }
      if (a.type === 'delete') {
        await api.post('/api/dispute/delete', { id: a.id });
        pushToast('Dispute deleted · audit kept');
      }
      refreshState();
    } catch (err) {
      pushToast('Error: ' + err.message);
    }
  };

  // ---- Banner ----
  const handleBanner = (choice) => {
    if (choice === 'accept' && banner) {
      pushToast('Added to thread', banner.threadTitle);
      refreshState();
    }
    setBanner(null);
  };

  // ---- Counts ----
  const counts = useMemo(() => {
    const threads  = appState?.threads  || [];
    const disputes = appState?.disputes || [];
    const followup = appState?.followUps || [];
    const done     = appState?.doneHistory || {};

    const opps = appState?.opportunities || [];
    return {
      todo:             threads.reduce((n,t) => n + t.tasks.filter(x=>!x.doneAt && !x.deletedAt).length, 0),
      done:             Object.values(done).flat().length,
      followup:         followup.length,
      disputes:         disputes.filter(d => d.state !== 'resolved').length,
      disputesEsc:      disputes.filter(d => d.state === 'escalated').length,
      opportunitiesNew: opps.filter(o => o.status === 'new').length || undefined,
      deleted:          (
        threads.reduce((n,t) => n + t.tasks.filter(x => x.isManual && x.deletedAt).length, 0) +
        (appState?.standaloneManualTasks||[]).filter(x => x.deletedAt).length +
        (appState?.dismissedFollowUps||[]).length
      ) || undefined,
    };
  }, [appState]);

  // ---- Update page title with badge ----
  useEffect(() => {
    document.title = counts.todo > 0
      ? `(${counts.todo}) ATLAS Email Agent — Elite Roads`
      : 'ATLAS Email Agent — Elite Roads';
  }, [counts.todo]);

  // ---- Loading ----
  if (authStatus === null) {
    return (
      <div className="auth-screen">
        <div className="auth-card" style={{textAlign:'center'}}>
          <I.spin style={{width:28, height:28, color:'var(--ink-3)', margin:'0 auto'}}/>
          <p style={{marginTop:12, color:'var(--ink-3)'}}>Loading…</p>
        </div>
      </div>
    );
  }

  if (authStatus === false) {
    return <AuthScreen error={authError} />;
  }

  if (!appState) {
    return (
      <div className="auth-screen">
        <div className="auth-card" style={{textAlign:'center'}}>
          <I.spin style={{width:28, height:28, color:'var(--ink-3)', margin:'0 auto'}}/>
          <p style={{marginTop:12, color:'var(--ink-3)'}}>Loading state…</p>
        </div>
      </div>
    );
  }

  const currentThread = openTask
    ? appState.threads.find(th => th.tasks.some(x => x.id === openTask.id))
    : null;

  return (
    <div className="app" data-rail={showRail ? 'true' : 'false'} data-density="compact" data-accent="green">
      <Sidebar view={view} setView={setView} counts={counts} employee={appState.employee} profile={appState.profile}
               activeMailbox={activeMailbox} mailboxes={mailboxes} onMailboxSwitch={handleMailboxSwitch} />
      <Topbar
        view={view}
        scanning={appState.scanning}
        lastScan={appState.lastScanAt}
        nextScanAt={appState.nextScanAt}
        onScan={handleScan}
        showRail={showRail}
        onToggleRail={() => setShowRail(r => !r)}
        onRefreshAll={handleRefreshAll}
        refreshingAll={refreshingAll}
      />

      <main className="main">
        {view === 'todo' && (
          <TodoView
            threads={appState.threads || []}
            onCheck={handleCheck}
            onOpenTask={(t, th) => { setOpenTask(t); setOpenThread(th); }}
            banner={banner}
            onBanner={handleBanner}
            onRefresh={refreshState}
            dismissedFollowUps={appState.dismissedFollowUps || []}
            standaloneManualTasks={appState.standaloneManualTasks || []}
            onCheckStandalone={handleCheckStandalone}
          />
        )}
        {view === 'done' && <DoneView doneHistory={appState.doneHistory} onUndo={refreshState} />}
        {view === 'deleted' && <RecentlyDeletedView
          threads={appState.threads || []}
          standaloneManualTasks={appState.standaloneManualTasks || []}
          dismissedFollowUps={appState.dismissedFollowUps || []}
          onRefresh={refreshState}
        />}
        {view === 'followup' && <FollowupsView items={appState.followUps || []} onRefresh={refreshState} />}
        {view === 'disputes' && (
          <DisputesView
            disputes={appState.disputes || []}
            onAction={handleDispute}
            onRefresh={refreshState}
          />
        )}
        {view === 'fleet-kb' && <FleetView />}
        {view === 'tenders-inbox' && <TenderView key={refreshKey} onCreateOpportunity={() => setView('opportunities')} />}
        {view === 'opportunities'  && <OpportunitiesView />}
        {view === 'move-log'       && <MoveLogView />}
        {view === 'todos' && (
          <TodosView
            todos={appState.todos || []}
            threads={appState.threads || []}
            onRefresh={refreshState}
          />
        )}
        {view === 'folders' && <FolderRulesView folderRules={appState.folderRules} onRefresh={refreshState} />}
        {view === 'style' && (
          <ReplyStyleView
            employee={appState.employee}
            currentInterface={appState.profile?.interface || 'general'}
            onSave={async (rs) => {
              await api.post('/api/settings/reply', rs);
              pushToast('Reply style saved');
              refreshState();
            }}
            onInterfaceChange={async (iface) => {
              await api.post('/api/interface', { interface: iface });
              pushToast('Workspace changed — reloading…');
              setTimeout(() => window.location.reload(), 800);
            }}
          />
        )}
      </main>

      {showRail && (
        <ActivityRail
          log={appState.log || []}
          pipelineStep={appState.pipelineStep || 6}
          stats={appState.stats}
          onCollapse={() => setShowRail(false)}
        />
      )}

      <ToastHost toasts={toasts} remove={removeToast} />

      {openTask && (currentThread || openThread) && (
        <TaskModal
          task={openTask}
          thread={currentThread || openThread}
          onClose={() => { setOpenTask(null); setOpenThread(null); }}
          onCheck={() => handleCheck((currentThread || openThread).id, openTask.id)}
          onSend={refreshState}
        />
      )}
    </div>
  );
}

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