// Root app: assemble everything + tweaks

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "accent": "electric",
  "density": "normal",
  "lang": "en",
  "issueLayout": "split",
  "agentStyle": "dialog",
  "sidebarCollapsed": false
}/*EDITMODE-END*/;

const App = () => {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const { theme, accent, density, lang, issueLayout, agentStyle, sidebarCollapsed } = tweaks;
  const [page, setPage] = useState('dashboard');
  const [adminSection, setAdminSection] = useState('general');
  const [, setBump] = useState(0);
  const [newIssueOpen, setNewIssueOpen] = useState(false);
  const [drawerOpen, setDrawerOpen] = useState(false);

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
    document.documentElement.setAttribute('data-accent', accent);
    document.documentElement.setAttribute('data-density', density);
  }, [theme, accent, density]);

  // ⌘B / Ctrl-B to toggle sidebar; ⌘, to open Settings
  useEffect(() => {
    const onKey = (e) => {
      const tag = (e.target?.tagName || '').toLowerCase();
      const inField = tag === 'input' || tag === 'textarea' || e.target?.isContentEditable;
      if ((e.metaKey || e.ctrlKey) && (e.key === 'b' || e.key === 'B')) {
        if (inField) return;
        e.preventDefault();
        setTweak('sidebarCollapsed', !sidebarCollapsed);
      }
      if ((e.metaKey || e.ctrlKey) && e.key === ',') {
        if (inField) return;
        e.preventDefault();
        setAdminSection('general');
        setPage('admin');
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [sidebarCollapsed]);

  const setLang = (v) => setTweak('lang', v);
  const setTheme = (v) => setTweak('theme', v);

  const crumbMap = {
    dashboard: [I18N[lang].dashboard],
    inbox: [I18N[lang].inbox],
    notes: [I18N[lang].notes],
    issues: [I18N[lang].issues],
    kanban: [I18N[lang].kanban],
    projects: [I18N[lang].projects],
    'project-detail': [(PROJECTS.find(p=>p.id===window.__currentProj)||PROJECTS[0]).name],
    teams: [I18N[lang].teams],
    admin: ['Settings', (ADMIN_SECTIONS.find(s => s.id === adminSection) || ADMIN_SECTIONS[0]).label],
    engines: [I18N[lang].engines],
    nodes: [I18N[lang].nodes],
    'node-detail': [I18N[lang].nodes, (NODES.find(n=>n.id===window.__currentNode)||NODES[0]).name],
    skills: [I18N[lang].skills],
    operators: [I18N[lang].workflows || 'Workflows'],
    'issue-detail': [I18N[lang].issues, (window.__currentIssue || 'ATL-412')],
  };
  const crumbs = crumbMap[page] || [I18N[lang].dashboard];

  // force rerender when nav switches project/issue via window.__
  const onNav = (p) => { setPage(p); setDrawerOpen(false); setTimeout(() => setBump(x=>x+1), 0); };

  let pageEl;
  switch (page) {
    case 'dashboard': pageEl = <Dashboard lang={lang} onNav={onNav} />; break;
    case 'issues': pageEl = <IssuesList onNav={onNav} />; break;
    case 'projects': pageEl = <Projects onNav={onNav} />; break;
    case 'project-detail': pageEl = <ProjectDetail onNav={onNav} />; break;
    case 'teams': pageEl = <Teams />; break;
    case 'admin': pageEl = <AdminPage section={adminSection} setSection={setAdminSection} />; break;
    case 'engines': // legacy alias
    case 'nodes': pageEl = <Nodes onNav={onNav} />; break;
    case 'node-detail': pageEl = <NodeDetail onNav={onNav} />; break;
    case 'skills': pageEl = <Skills />; break;
    case 'operators': pageEl = <OperatorsPage onNav={onNav} />; break;
    case 'issue-detail': pageEl = <IssueDetail lang={lang} layout={issueLayout} panelStyle={agentStyle} />; break;
    case 'inbox': pageEl = <InboxPage onNav={onNav} />; break;
    case 'notes': pageEl = <NotesPage onNav={onNav} />; break;
    default: pageEl = <Dashboard lang={lang} onNav={onNav} />;
  }

  return (
    <>
      <div className={`app ${drawerOpen ? 'drawer-open' : ''}`} data-screen-label={page}>
        <div className="sidebar-scrim" onClick={() => setDrawerOpen(false)} />
        <Sidebar page={page} setPage={onNav} lang={lang} collapsed={sidebarCollapsed} onToggle={() => setTweak('sidebarCollapsed', !sidebarCollapsed)} theme={theme} setTheme={setTheme} setLang={setLang} onSearch={() => setDrawerOpen(true)} />
        <div className="main">
          <Topbar crumbs={crumbs} page={page} setPage={onNav} lang={lang} onNewIssue={() => setNewIssueOpen(true)} onMenu={() => setDrawerOpen(v => !v)} />
          <div className="content" key={page}>{pageEl}</div>
        </div>
        <MobileTabBar page={page} setPage={onNav} unread={8} />
      </div>

      <NewIssueModal open={newIssueOpen} onClose={() => setNewIssueOpen(false)} />

      <TweaksPanel>
        <TweakSection label="Appearance" />
        <TweakRadio label="Theme" value={theme} onChange={v => setTweak('theme', v)} options={[
          { value: 'light', label: 'Light' },
          { value: 'dark', label: 'Dark' },
        ]}/>
        <TweakRadio label="Accent" value={accent} onChange={v => setTweak('accent', v)} options={[
          { value: 'electric', label: 'Electric' },
          { value: 'amber', label: 'Amber' },
          { value: 'mint', label: 'Mint' },
        ]}/>
        <TweakRadio label="Density" value={density} onChange={v => setTweak('density', v)} options={[
          { value: 'compact', label: 'Compact' },
          { value: 'normal', label: 'Normal' },
          { value: 'cozy', label: 'Cozy' },
        ]}/>
        <TweakRadio label="Language" value={lang} onChange={v => setTweak('lang', v)} options={[
          { value: 'en', label: 'EN' },
          { value: 'zh', label: '中' },
        ]}/>
        <TweakToggle label="Collapse sidebar (⌘B)" value={sidebarCollapsed} onChange={v => setTweak('sidebarCollapsed', v)} />

        <TweakSection label="Issue detail" />
        <TweakRadio label="Layout" value={issueLayout} onChange={v => setTweak('issueLayout', v)} options={[
          { value: 'drawer', label: 'Drawer' },
          { value: 'split', label: 'Split' },
          { value: 'full', label: 'Full-page' },
        ]}/>
        <TweakRadio label="Agent panel" value={agentStyle} onChange={v => setTweak('agentStyle', v)} options={[
          { value: 'dialog', label: 'Dialog' },
          { value: 'terminal', label: 'Terminal' },
        ]}/>

        <TweakSection label="Jump to page" />
        <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:6,padding:'4px 0'}}>
          {[
            ['dashboard','Dashboard'],['issues','Issues'],
            ['issue-detail','Issue detail'],['projects','Projects'],['project-detail','Project detail'],
            ['teams','Teams'],['nodes','Nodes'],['node-detail','Node detail'],['skills','Skills'],['operators','Workflows'],
          ].map(([k,l]) => (
            <TweakButton key={k} label={l} onClick={() => onNav(k)} secondary={page!==k} />
          ))}
        </div>
      </TweaksPanel>
    </>
  );
};

// Inbox — lightweight notification stream. Awareness, not action.
// Click any row to jump to the issue/entity where actions actually live.
const INBOX_KIND_META = {
  approval:      { label: 'Approval',     color: 'var(--status-working)' },
  clarification: { label: 'Clarify',      color: 'var(--accent)' },
  review:        { label: 'Review',       color: 'var(--engine-claude)' },
  conflict:      { label: 'Conflict',     color: 'var(--status-blocked)' },
  policy:        { label: 'Policy',       color: 'var(--status-blocked)' },
  budget:        { label: 'Budget',       color: 'var(--status-working)' },
  mention:       { label: 'Mention',      color: 'var(--fg-3)' },
};

// How to phrase the notification in one line, second person, concise.
const inboxVerb = (item) => {
  switch (item.kind) {
    case 'approval':      return 'needs your approval';
    case 'clarification': return 'is waiting for clarification';
    case 'review':        return 'opened a PR for review';
    case 'conflict':      return 'flagged a conflict';
    case 'policy':        return 'was blocked by policy';
    case 'budget':        return 'hit a budget ceiling';
    case 'mention':       return 'mentioned you';
    default:              return '';
  }
};

const InboxPage = ({ onNav }) => {
  const [filter, setFilter] = React.useState('all');
  const [readIds, setReadIds] = React.useState(new Set());
  const filtered = filter === 'all' ? INBOX : INBOX.filter(i => i.kind === filter);

  const counts = INBOX.reduce((acc, i) => { acc[i.kind] = (acc[i.kind]||0)+1; return acc; }, {});
  const kinds = ['all', ...Object.keys(INBOX_KIND_META)];

  const openItem = (item) => {
    setReadIds(s => new Set([...s, item.id]));
    if (item.issue) { window.__currentIssue = item.issue; onNav('issue-detail'); }
  };

  return (
    <div className="fade-in" style={{display:'flex',flexDirection:'column',height:'100%',minHeight:0}}>
      <div className="page-head">
        <div>
          <div className="page-title">Inbox</div>
          <div className="page-sub">{INBOX.length - readIds.size} unread · notifications from agents and teammates</div>
        </div>
        <span className="spacer" />
        <button className="ibtn bordered" onClick={() => setReadIds(new Set(INBOX.map(i=>i.id)))}>
          <Icon name="check" size={13} /> Mark all read
        </button>
      </div>

      <div style={{display:'flex',gap:6,padding:'0 24px 12px',borderBottom:'1px solid var(--border-subtle)',flexWrap:'wrap'}}>
        {kinds.map(k => {
          const meta = k === 'all' ? { label: 'All', color: 'var(--fg)' } : INBOX_KIND_META[k];
          const n = k === 'all' ? INBOX.length : (counts[k] || 0);
          const active = filter === k;
          return (
            <button key={k}
              onClick={() => setFilter(k)}
              className={`ibtn ${active ? '' : 'bordered'}`}
              style={{
                fontSize: 12,
                color: active ? 'var(--bg)' : 'var(--fg-1)',
                background: active ? 'var(--fg)' : undefined,
              }}>
              {k !== 'all' && <span style={{width:7,height:7,borderRadius:50,background:meta.color,display:'inline-block'}} />}
              {meta.label}
              <span className="mono" style={{fontSize:10.5,opacity:0.65,marginLeft:2}}>{n}</span>
            </button>
          );
        })}
      </div>

      <div style={{flex:1,overflow:'auto'}}>
        <div style={{maxWidth:860,margin:'0 auto',padding:'4px 0 40px'}}>
          {filtered.map(item => (
            <InboxRow key={item.id} item={item} read={readIds.has(item.id)} onClick={() => openItem(item)} />
          ))}
          {filtered.length === 0 && (
            <div style={{padding:60,textAlign:'center',color:'var(--fg-3)',fontSize:13}}>No notifications</div>
          )}
        </div>
      </div>
    </div>
  );
};

const InboxRow = ({ item, read, onClick }) => {
  const meta = INBOX_KIND_META[item.kind];
  const agentLetter = item.engine === 'claude' ? 'C' : item.engine === 'codex' ? 'O' : item.engine === 'gemini' ? 'G' : null;
  const actorName = agentLetter ? item.agent : (item.who || 'System');

  return (
    <div onClick={onClick}
      style={{
        padding:'14px 20px',
        borderBottom:'1px solid var(--border-subtle)',
        display:'grid',
        gridTemplateColumns:'10px 24px 1fr auto',
        gap:12,
        alignItems:'flex-start',
        cursor:'pointer',
        opacity: read ? 0.55 : 1,
        transition: 'background 120ms ease',
      }}
      onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-hover)'}
      onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>

      {/* Unread dot */}
      <div style={{paddingTop:7}}>
        {!read && <span style={{display:'block',width:7,height:7,borderRadius:50,background:meta.color}} />}
      </div>

      {/* Actor avatar */}
      {agentLetter ? (
        <span className={`avatar agent ${item.engine}`} style={{width:24,height:24,fontSize:11,borderWidth:0,marginTop:1}}>{agentLetter}</span>
      ) : (
        <span className="avatar" style={{width:24,height:24,fontSize:10.5,marginTop:1}}>{(item.who||'SY').split(' ').map(x=>x[0]).join('').slice(0,2)}</span>
      )}

      {/* Body */}
      <div style={{minWidth:0}}>
        <div style={{fontSize:13,lineHeight:1.5,color:'var(--fg-1)',marginBottom:3}}>
          <span style={{fontWeight: read ? 450 : 550, color: 'var(--fg)'}}>{actorName}</span>
          <span style={{color:'var(--fg-2)'}}> {inboxVerb(item)} on </span>
          <span className="mono" style={{color:'var(--accent)',fontWeight:500}}>{item.issue}</span>
        </div>
        <div style={{fontSize:12.5,color:'var(--fg-2)',lineHeight:1.55,overflow:'hidden',textOverflow:'ellipsis',display:'-webkit-box',WebkitLineClamp:1,WebkitBoxOrient:'vertical'}}>
          {item.title}
        </div>
      </div>

      {/* Kind tag + time */}
      <div style={{display:'flex',flexDirection:'column',alignItems:'flex-end',gap:4,whiteSpace:'nowrap'}}>
        <span style={{
          fontSize:10.5,
          fontFamily:'Geist Mono',
          textTransform:'uppercase',
          letterSpacing:'0.06em',
          color: meta.color,
          fontWeight:600,
        }}>{meta.label}</span>
        <span className="mono" style={{fontSize:10.5,color:'var(--fg-3)'}}>{item.pausedFor}</span>
      </div>
    </div>
  );
};

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