// app.jsx — Idea Pipeline shell, state, routing, tweaks

const { useState, useEffect, useMemo } = React;
const { PROJECTS, USERS } = window.SEED;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "violet",
  "dark": false,
  "density": "regular",
  "font": "Plus Jakarta Sans"
}/*EDITMODE-END*/;

const THEMES = {
  violet: 275, blue: 248, teal: 192, green: 152, amber: 60, rose: 12,
};

function App() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [authUser, setAuthUser] = useState(null);
  const [booting, setBooting] = useState(true);
  const [projects, setProjects] = useState([]);
  const [roles, setRoles] = useState({});
  const [view, setView] = useState('ideas');           // ideas | project | mytasks | roles
  const [activeId, setActiveId] = useState(null);
  const [open, setOpen] = useState(null);              // { projectId, taskId }
  const [newIdea, setNewIdea] = useState(false);
  const [query, setQuery] = useState('');
  const [projTab, setProjTab] = useState('board');     // board | report

  // apply theme tokens
  useEffect(() => {
    const r = document.documentElement;
    r.dataset.dark = t.dark ? '1' : '0';
    r.dataset.density = t.density;
    r.style.setProperty('--primary-h', THEMES[t.theme] ?? 275);
    r.style.setProperty('--font-ui', `'${t.font}', system-ui, sans-serif`);
  }, [t.theme, t.dark, t.density, t.font]);

  // ---- auth + workspace bootstrap (Firebase) ----
  useEffect(() => {
    const unsub = window.fb.auth.onAuthStateChanged(async (user) => {
      if (!user) { setAuthUser(null); setBooting(false); return; }
      setBooting(true);
      try {
        await window.fb.ensureProfile(user);                // first sign-up self-heals here
        const users = await window.fb.loadUsers();
        const seedUsers = window.SEED.USERS;                 // mutate the shared array in place
        seedUsers.length = 0; users.forEach((u) => seedUsers.push(u));
        const projs = await window.fb.loadProjects();
        setProjects(projs);
        setRoles(Object.fromEntries(users.map((u) => [u.id, u.accessRole])));
        window.SEED.ME = user.uid;
        setAuthUser(user.uid);
      } catch (e) {
        console.error('Failed to load workspace', e);
        alert('Could not load your workspace: ' + (e.message || e));
        setAuthUser(null);
      } finally {
        setBooting(false);
      }
    });
    return () => unsub();
  }, []);

  const logout = () => { window.fb.signOut(); setView('ideas'); setActiveId(null); setOpen(null); };

  // ---- auth / loading gates ----
  if (booting) return <window.Splash />;
  if (!authUser) return <window.Login />;
  window.SEED.ME = authUser;
  const ME = authUser;
  const myRole = roles[ME];
  const canCreate = window.can(myRole, 'Create a new idea');

  const active = projects.find((p) => p.id === activeId);
  const openTask = open && projects.find((p) => p.id === open.projectId)?.tasks.find((x) => x.id === open.taskId);
  const openProject = open && projects.find((p) => p.id === open.projectId);

  // ---- mutations ---- (each write also persists the affected project doc to Firestore)
  const persist = (project) => { window.fb.saveProject(project).catch((e) => console.error('Save failed', e)); };

  const mutateTasks = (projectId, fn) =>
    setProjects((ps) => ps.map((p) => {
      if (p.id !== projectId) return p;
      const np = { ...p, tasks: fn(p.tasks) };
      persist(np); return np;
    }));

  const moveTask = (taskId, stage) =>
    setProjects((ps) => ps.map((p) => {
      if (!p.tasks.some((x) => x.id === taskId)) return p;
      const np = { ...p, tasks: p.tasks.map((x) => x.id === taskId ? { ...x, stage } : x) };
      persist(np); return np;
    }));

  const updateTask = (projectId, taskId, patch) =>
    mutateTasks(projectId, (tasks) => tasks.map((x) => x.id === taskId ? { ...x, ...patch } : x));

  const mkComment = (text) => ({ id: 'c' + Date.now(), author: ME, text, time: 'just now' });
  const addProjectComment = (projectId, text) =>
    setProjects((ps) => ps.map((p) => {
      if (p.id !== projectId) return p;
      const np = { ...p, comments: [...(p.comments || []), mkComment(text)] };
      persist(np); return np;
    }));
  const addTaskComment = (projectId, taskId, text) =>
    mutateTasks(projectId, (tasks) => tasks.map((x) => x.id === taskId ? { ...x, comments: [...(x.comments || []), mkComment(text)] } : x));

  const addTask = (projectId, stage) => {
    const proj = projects.find((p) => p.id === projectId);
    const id = 't' + Date.now();
    mutateTasks(projectId, (tasks) => [...tasks, {
      id, title: 'New task', stage, assignee: proj.team[0], priority: 'medium', due: 'TBD', desc: '', cost: 0, spentOn: '', comments: [],
    }]);
    setOpen({ projectId, taskId: id });
  };

  const createIdea = (data) => {
    const id = 'p' + Date.now();
    const created = new Date().toLocaleString('en-US', { month: 'short', year: 'numeric' });
    const project = {
      id, ...data, status: 'idea', created, order: Date.now(), comments: [],
      tasks: [
        { id: id + 'a', title: 'Validate the problem with 10 people', stage: 'pending', assignee: data.owner, priority: 'high', due: 'TBD', desc: 'Talk to real potential customers before building.', cost: 0, spentOn: '', comments: [] },
        { id: id + 'b', title: 'Define MVP scope', stage: 'pending', assignee: data.team[0], priority: 'high', due: 'TBD', desc: '', cost: 0, spentOn: '', comments: [] },
        { id: id + 'c', title: 'Sketch the core flow', stage: 'pending', assignee: data.team[data.team.length - 1], priority: 'medium', due: 'TBD', desc: '', cost: 0, spentOn: '', comments: [] },
      ],
    };
    setProjects((ps) => [project, ...ps]);
    persist(project);
    setNewIdea(false);
    setActiveId(id);
    setView('project');
  };

  // role changes (owner only) — update state, the in-place roster, and persist to Firestore
  const changeRoles = (next) => {
    setRoles((prev) => {
      Object.keys(next).forEach((uid) => {
        if (next[uid] !== prev[uid]) window.fb.saveUserRole(uid, next[uid]).catch((e) => console.error('Role save failed', e));
      });
      window.SEED.USERS.forEach((u) => { if (next[u.id]) u.accessRole = next[u.id]; });
      return next;
    });
  };

  const goProject = (id) => { setActiveId(id); setView('project'); setProjTab('board'); setQuery(''); };

  return (
    <div className="app">
      {/* sidebar */}
      <nav className="sidebar">
        <div className="brand">
          <span className="brand-mark"><window.Icon name="bolt" size={18} stroke={2.2} /></span>
          <span className="brand-name">Idea<span style={{ color: 'var(--primary)' }}>Pipeline</span></span>
        </div>
        <div className="nav-group">
          <NavItem icon="grid" label="Business Ideas" on={view === 'ideas' || view === 'project'}
            onClick={() => { setView('ideas'); setQuery(''); }} />
          <NavItem icon="user" label="My Tasks" badge={projects.reduce((n, p) => n + p.tasks.filter((x) => x.assignee === ME && x.stage !== 'complete').length, 0)}
            on={view === 'mytasks'} onClick={() => { setView('mytasks'); setQuery(''); }} />
          <NavItem icon="users" label="Roles & Permissions" on={view === 'roles'}
            onClick={() => { setView('roles'); setQuery(''); }} />
        </div>

        <div className="nav-label">Active ideas</div>
        <div className="nav-group scroll">
          {projects.filter((p) => p.status !== 'launched').slice(0, 6).map((p) => (
            <button key={p.id} className={'nav-proj' + (activeId === p.id && view === 'project' ? ' on' : '')}
              onClick={() => goProject(p.id)}>
              <span className="nav-proj-dot" style={{ background: `oklch(0.6 0.15 ${window.SEED.IDEA_STATUS[p.status].hue})` }} />
              <span className="nav-proj-name">{p.name}</span>
              <span className="nav-proj-n">{p.tasks.filter((x) => x.stage !== 'complete').length}</span>
            </button>
          ))}
        </div>

        <div className="sidebar-foot">
          <window.Avatar id={ME} size={34} />
          <div style={{ minWidth: 0, flex: 1 }}>
            <div className="me-name">{window.userById(ME).name}</div>
            <div className="me-foot-role"><window.RolePill roleId={myRole} size="sm" /></div>
          </div>
          <button className="icon-btn" title="Sign out" onClick={logout}>
            <window.Icon name="logout" size={17} />
          </button>
        </div>
      </nav>

      {/* main */}
      <main className="main">
        <header className="topbar">
          {view === 'project' && active ? (
            <div className="crumbs">
              <button className="crumb-back" onClick={() => setView('ideas')}>
                <window.Icon name="chevronL" size={16} /> Ideas
              </button>
              <span className="crumb-sep">/</span>
              <span className="crumb-cur">{active.name}</span>
              <window.StatusPill status={active.status} />
            </div>
          ) : (
            <div className="searchbox">
              <window.Icon name="search" size={17} style={{ color: 'var(--text-faint)' }} />
              <input value={query} onChange={(e) => setQuery(e.target.value)}
                placeholder={view === 'mytasks' ? 'Search my tasks…' : 'Search ideas…'} />
            </div>
          )}
          <div style={{ flex: 1 }} />
          {canCreate && (
            <button className="btn-primary sm" onClick={() => setNewIdea(true)}>
              <window.Icon name="plus" size={16} /> New Idea
            </button>
          )}
        </header>

        <div className="content">
          {view === 'ideas' && (
            <window.IdeasView projects={projects} onOpen={goProject} onNew={() => setNewIdea(true)} query={query} canCreate={canCreate} />
          )}
          {view === 'roles' && (
            <window.RolesView roles={roles} setRoles={changeRoles} me={ME} />
          )}
          {view === 'project' && active && (
            <div className="project-view">
              <div className="project-hero">
                <div style={{ minWidth: 0 }}>
                  <span className="proj-mono" style={{ color: 'var(--text-faint)' }}>{active.category} · started {active.created}</span>
                  <h1 className="view-title" style={{ marginTop: 4 }}>{active.name}</h1>
                  <p className="view-sub" style={{ maxWidth: 560 }}>{active.tagline}</p>
                </div>
                <div className="hero-side">
                  <div className="hero-cost">
                    <span className="hero-cost-lbl"><window.Icon name="wallet" size={14} stroke={2} /> Total cost</span>
                    <span className="hero-cost-val">{window.fmtMoney(active.tasks.reduce((n, t) => n + (t.cost || 0), 0))}</span>
                  </div>
                  <div style={{ width: 200 }}>
                    <window.Progress value={active.tasks.filter((x) => x.stage === 'complete').length} total={active.tasks.length} />
                    <div className="hero-team">
                      <window.AvatarStack ids={active.team} size={28} max={6} />
                    </div>
                  </div>
                </div>
              </div>
              <div className="proj-tabs">
                <button className={'proj-tab' + (projTab === 'board' ? ' on' : '')} onClick={() => setProjTab('board')}>
                  <window.Icon name="board" size={16} /> Task Board
                </button>
                <button className={'proj-tab' + (projTab === 'discussion' ? ' on' : '')} onClick={() => setProjTab('discussion')}>
                  <window.Icon name="comment" size={16} /> Discussion
                  {active.comments && active.comments.length > 0 && <span className="tab-count">{active.comments.length}</span>}
                </button>
                <button className={'proj-tab' + (projTab === 'report' ? ' on' : '')} onClick={() => setProjTab('report')}>
                  <window.Icon name="receipt" size={16} /> Expense Report
                </button>
              </div>
              {projTab === 'board' && (
                <window.Board project={active} onOpen={(taskId) => setOpen({ projectId: active.id, taskId })}
                  moveTask={moveTask} onAdd={(stage) => addTask(active.id, stage)} />
              )}
              {projTab === 'discussion' && (
                <div className="discussion-scroll">
                  <div className="discussion-wrap">
                    <h2 className="disc-title">Project Discussion</h2>
                    <p className="disc-sub">Team notes & decisions for {active.name}. Separate from task-level comments.</p>
                    <div className="disc-panel">
                      <window.CommentThread comments={active.comments || []}
                        onAdd={(text) => addProjectComment(active.id, text)}
                        placeholder={`Share an update on ${active.name}…`}
                        empty="No project comments yet — kick off the discussion." autoScroll />
                    </div>
                  </div>
                </div>
              )}
              {projTab === 'report' && (
                <div className="report-scroll"><window.ExpenseReport project={active} /></div>
              )}
            </div>
          )}
          {view === 'mytasks' && (
            <window.MyTasksView projects={projects} query={query}
              onOpenTask={(projectId, taskId) => setOpen({ projectId, taskId })} />
          )}
        </div>
      </main>

      {openTask && (
        <window.TaskDrawer task={openTask} project={openProject} onClose={() => setOpen(null)}
          onChange={(patch) => updateTask(open.projectId, open.taskId, patch)}
          onAddComment={(text) => addTaskComment(open.projectId, open.taskId, text)} />
      )}
      {newIdea && <window.NewIdeaModal onClose={() => setNewIdea(false)} onCreate={createIdea} />}

      <window.TweaksPanel>
        <window.TweakSection label="Theme" />
        <window.TweakSelect label="Accent" value={t.theme}
          options={['violet', 'blue', 'teal', 'green', 'amber', 'rose']}
          onChange={(v) => setTweak('theme', v)} />
        <window.TweakToggle label="Dark mode" value={t.dark} onChange={(v) => setTweak('dark', v)} />
        <window.TweakSection label="Layout" />
        <window.TweakRadio label="Density" value={t.density}
          options={['compact', 'regular', 'comfy']} onChange={(v) => setTweak('density', v)} />
        <window.TweakSelect label="Font" value={t.font}
          options={['Plus Jakarta Sans', 'Manrope', 'Figtree', 'Inter Tight']}
          onChange={(v) => setTweak('font', v)} />
      </window.TweaksPanel>
    </div>
  );
}

function NavItem({ icon, label, on, onClick, badge }) {
  return (
    <button className={'nav-item' + (on ? ' on' : '')} onClick={onClick}>
      <window.Icon name={icon} size={18} />
      <span>{label}</span>
      {badge > 0 && <span className="nav-badge">{badge}</span>}
    </button>
  );
}

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