// Hermes Console — App orchestrator

const { useState: useStateApp, useEffect: useEffectApp, useRef: useRefApp, useMemo: useMemoApp, useCallback: useCallbackApp } = React;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const agents = window.HERMES_AGENTS;

  // --- top-level view: 'console' | 'projects' | 'library' | 'settings' ---
  const [view, setView] = useStateApp('projects');
  // --- selected project ---
  const [projects, setProjects] = useStateApp(window.PROJECTS);
  const [currentProjectId, setCurrentProjectId] = useStateApp(2891);
  const currentProject = projects.find(p => p.id === currentProjectId) || projects[0];

  // --- core run state ---
  const [activeId, setActiveId] = useStateApp('req');
  const [runState, setRunState] = useStateApp('idle'); // idle | running | done
  const [runningId, setRunningId] = useStateApp(null);
  const [completed, setCompleted] = useStateApp(new Set());

  // --- chat state per agent ---
  const initialChats = () => ({
    req: [],
    prd: [],
    proto: [],
  });
  const [chats, setChats] = useStateApp(initialChats);
  const [drafts, setDrafts] = useStateApp({ req: '', prd: '', proto: '' });
  const [typingFor, setTypingFor] = useStateApp(null);

  // --- memory state ---
  const [memoryFill, setMemoryFill] = useStateApp(() =>
    Object.fromEntries(window.MEMORY_LAYERS.map(l => [l.id, l.fillBase]))
  );
  const [writingLayerId, setWritingLayerId] = useStateApp(null);
  const [recentWrites, setRecentWrites] = useStateApp([]);

  // --- skills state ---
  const [skillsByAgent, setSkillsByAgent] = useStateApp(() => {
    const out = {};
    for (const k of Object.keys(window.SKILLS_BY_AGENT)) {
      out[k] = window.SKILLS_BY_AGENT[k].map(s => ({ ...s, trend: [...s.trend] }));
    }
    return out;
  });
  const [flashSkill, setFlashSkill] = useStateApp(null);

  // --- inspector tab ---
  const [tab, setTab] = useStateApp('memory');

  // theme
  useEffectApp(() => {
    document.documentElement.setAttribute('data-theme', t.theme);
  }, [t.theme]);

  // accent override
  useEffectApp(() => {
    if (t.accent) {
      document.documentElement.style.setProperty('--accent', t.accent);
      // build soft + line variants
      document.documentElement.style.setProperty('--accent-soft', t.accent + '1A');
      document.documentElement.style.setProperty('--accent-line', t.accent + '70');
    }
  }, [t.accent]);

  const activeAgent = agents.find(a => a.id === activeId) || agents[0];

  // ------- helpers -------
  const time = () => {
    const d = new Date();
    return `${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}:${String(d.getSeconds()).padStart(2,'0')}`;
  };

  const writeMemory = useCallbackApp((layerId, source, detail) => {
    setWritingLayerId(layerId);
    setMemoryFill(prev => ({ ...prev, [layerId]: prev[layerId] + Math.floor(Math.random() * 40 + 20) }));
    const t = time();
    setRecentWrites(prev => [...prev.slice(-12), { layerId, t: t.slice(0,5), s: source, d: detail }]);
    setTimeout(() => setWritingLayerId(null), 800);
  }, []);

  const bumpSkill = useCallbackApp((agentId, skillName) => {
    setSkillsByAgent(prev => {
      const nextList = prev[agentId].map(s => {
        if (s.name !== skillName) return s;
        const nextTrend = [...s.trend.slice(1), s.trend[s.trend.length - 1] + Math.floor(Math.random() * 3 + 2)];
        return { ...s, invocations: s.invocations + 1, trend: nextTrend };
      });
      return { ...prev, [agentId]: nextList };
    });
    setFlashSkill(skillName);
    setTimeout(() => setFlashSkill(null), 700);
  }, []);

  // ------- pipeline run -------
  const speed = t.demoSpeed || 1;
  const scaled = (ms) => Math.max(150, Math.round(ms / speed));

  const runPipeline = async (initialReq) => {
    setRunState('running');
    setCompleted(new Set());

    // user message into req
    const userMsg = initialReq || drafts.req || '电商 App 用户反馈管理系统：客服与产品双角色，看板视图，支持工单流转与标签体系。';
    setChats(prev => ({
      ...prev,
      req: [...prev.req, { role: 'user', text: userMsg, t: time() }],
    }));
    setDrafts(prev => ({ ...prev, req: '' }));

    await sleep(scaled(400));

    // for each agent in sequence
    const ORDER = ['req', 'prd', 'proto'];
    for (let i = 0; i < ORDER.length; i++) {
      const id = ORDER[i];
      setActiveId(id);
      setRunningId(id);
      setTab(i === 0 ? 'memory' : i === 1 ? 'skills' : 'memory');

      // L0 immediate context fills as agent thinks
      writeMemory('L0', 'reasoning', `${id} 启动推理`);
      await sleep(scaled(300));

      // play scripted messages for this agent
      const script = window.DEMO_SCRIPT[id];
      for (const step of script) {
        setTypingFor(id);
        await sleep(scaled(step.delay));
        setTypingFor(null);
        setChats(prev => ({
          ...prev,
          [id]: [...prev[id], { role: 'agent', text: step.text, kind: step.kind, t: time() }],
        }));

        // side effects per step kind
        if (step.kind === 'tool') {
          const skillName = pickSkill(id);
          if (skillName) bumpSkill(id, skillName);
          writeMemory('L0', 'tool', step.text.split('(')[0]);
        } else if (step.kind === 'memory') {
          writeMemory('L2', 'project', step.text.replace('已写入 项目记忆: ', ''));
        } else {
          // regular reasoning -> bump a skill subtly
          if (Math.random() < 0.5) {
            const skillName = pickSkill(id);
            if (skillName) bumpSkill(id, skillName);
          }
        }
        await sleep(scaled(180));
      }

      // mark agent complete -> write task memory
      writeMemory('L1', 'artifact',
        id === 'req' ? 'requirements.md (27 stories)' :
        id === 'prd' ? 'prd.v0.1.md (4 chapters)' :
        'prototype.html (5 pages)');
      await sleep(scaled(400));

      setCompleted(prev => new Set([...prev, id]));
      setRunningId(null);

      // hand-off
      if (i < ORDER.length - 1) {
        const next = ORDER[i + 1];
        const handoff = id === 'req'
          ? '已将 27 条 user story + 实体清单转交。'
          : id === 'prd'
          ? '已将 PRD v0.1 转交。'
          : '';
        setChats(prev => ({
          ...prev,
          [next]: [...prev[next], { role: 'user', text: `[Pipeline 移交] ${handoff}`, t: time() }],
        }));
        // L3 — sediment a long-term pattern after handoff
        writeMemory('L3', 'pattern', `${id} → ${next} 链路 +1 经验`);
        await sleep(scaled(300));
      }
    }

    // final long-term consolidation
    writeMemory('L3', 'sediment', '本次 pipeline 模式存档');
    setRunState('done');
  };

  function pickSkill(agentId) {
    const list = window.SKILLS_BY_AGENT[agentId] || [];
    if (list.length === 0) return null;
    return list[Math.floor(Math.random() * list.length)].name;
  }

  function sleep(ms) {
    return new Promise(r => setTimeout(r, ms));
  }

  const onSend = () => {
    const text = drafts[activeId].trim();
    if (!text || typingFor) return;
    if (runState === 'idle' && activeId === 'req') {
      runPipeline(text);
      return;
    }
    setChats(prev => ({
      ...prev,
      [activeId]: [...prev[activeId], { role: 'user', text, t: time() }],
    }));
    setDrafts(prev => ({ ...prev, [activeId]: '' }));
    // simulate response
    setTypingFor(activeId);
    setTimeout(() => {
      setTypingFor(null);
      setChats(prev => ({
        ...prev,
        [activeId]: [...prev[activeId], {
          role: 'agent',
          text: '已收到补充信息，正在更新记忆与产物。可点击右上角 ▶ 启动 Pipeline 触发完整流转。',
          t: time(),
        }],
      }));
      writeMemory('L1', 'note', text.slice(0, 32));
    }, 1100);
  };

  const onPreset = (key) => {
    const presets = {
      feedback: '电商 App 用户反馈管理系统：客服 + 产品双角色，支持反馈分类、工单流转、看板视图、SLA 追踪。',
      coupon: 'B 端优惠券中台：模板配置 + 发放策略 + 核销追踪 + 防薅羊毛风控。',
      dashboard: '业务数据看板：多租户、可拖拽组件、自定义指标、定时邮件报告。',
    };
    setDrafts(prev => ({ ...prev, [activeId]: presets[key] }));
  };

  const onReset = () => {
    setRunState('idle');
    setRunningId(null);
    setCompleted(new Set());
    setChats(initialChats());
    setRecentWrites([]);
    setMemoryFill(Object.fromEntries(window.MEMORY_LAYERS.map(l => [l.id, l.fillBase])));
    setActiveId('req');
  };

  // keyboard shortcut
  useEffectApp(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
        if (runState === 'idle') runPipeline();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [runState, drafts]);

  // memory layers w/ live fill
  const layersWithFill = window.MEMORY_LAYERS.map(l => ({
    ...l,
    fill: memoryFill[l.id],
  }));

  return (
    <div className="app">
      <Header
        runState={runState}
        onRun={() => runPipeline()}
        onReset={onReset}
        project={{ workspace: 'fenghuang-tech', name: view === 'console' ? `#${currentProject.id} ${currentProject.name}` : '所有项目' }}
        view={view}
        onBackToProjects={() => setView('projects')}
      />
      <div className="app-body">
        <NavRail view={view} setView={setView} />
        {view === 'console' && (
          <div className="console-grid">
            <AgentRail
              agents={agents}
              activeId={activeId}
              runningId={runningId}
              completed={completed}
              onSelect={setActiveId}
            />
            <div className="center">
              {t.showWorkflow && (
                <Workflow
                  agents={agents}
                  runningId={runningId}
                  completed={completed}
                  activeId={activeId}
                  onSelect={setActiveId}
                  runState={runState}
                />
              )}
              <Chat
                agent={activeAgent}
                messages={chats[activeId]}
                draft={drafts[activeId]}
                setDraft={(v) => setDrafts(prev => ({ ...prev, [activeId]: v }))}
                onSend={onSend}
                isAgentTyping={typingFor === activeId}
                onPresetSelect={onPreset}
              />
            </div>
            <Inspector
              tab={tab}
              setTab={setTab}
              layers={layersWithFill}
              writingLayerId={writingLayerId}
              recentWrites={recentWrites}
              agentId={activeId}
              skills={skillsByAgent[activeId] || []}
              flashSkill={flashSkill}
            />
          </div>
        )}
        {view === 'projects' && (
          <ProjectsView
            projects={projects}
            currentProjectId={currentProjectId}
            onOpenProject={(id) => { setCurrentProjectId(id); setView('console'); onReset(); }}
            onNewProject={() => { setView('console'); onReset(); setActiveId('req'); }}
          />
        )}
        {view === 'library' && <SkillLibraryView />}
        {view === 'settings' && <SettingsView />}
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Appearance">
          <TweakRadio
            label="Theme"
            value={t.theme}
            options={['light', 'dark']}
            onChange={(v) => setTweak('theme', v)}
          />
          <TweakColor
            label="Accent"
            value={t.accent}
            options={['#C77A2E', '#3D5BC4', '#1F8A5B', '#7A5AE0']}
            onChange={(v) => setTweak('accent', v)}
          />
        </TweakSection>
        <TweakSection label="Demo">
          <TweakSlider
            label="演示速度"
            value={t.demoSpeed}
            min={0.5}
            max={4}
            step={0.5}
            unit="×"
            onChange={(v) => setTweak('demoSpeed', v)}
          />
          <TweakToggle
            label="显示 Pipeline"
            value={t.showWorkflow}
            onChange={(v) => setTweak('showWorkflow', v)}
          />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

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