// Hermes Console — main app
// Three-pane enterprise console: Agent rail | Workflow + Chat | Memory & Skills inspector

const { useState, useEffect, useRef, useMemo, useCallback } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "demoSpeed": 1,
  "accent": "#C77A2E",
  "showWorkflow": true
}/*EDITMODE-END*/;

// ─── glyph color helpers ────────────────────────────────────────────────
function AgentGlyph({ agent }) {
  return (
    <span className="agent-glyph" style={{ background: agent.color }}>
      {agent.code.split('-')[0]}
    </span>
  );
}

// ─── Header ─────────────────────────────────────────────────────────────
function Header({ runState, onRun, onReset, project, view, onBackToProjects }) {
  const label = runState === 'idle' ? 'IDLE'
    : runState === 'done' ? 'COMPLETED'
    : 'RUNNING';
  return (
    <header className="hdr">
      <div className="hdr-brand">
        <div className="hdr-logo">H</div>
        <div className="hdr-title">HERMES<span className="v">v0.4.2-rc</span></div>
      </div>
      <nav className="pagenav">
        <a className="pn" href="/">Live Pipeline</a>
        <a className="pn active" href="/console/">控制台</a>
      </nav>
      <div className="hdr-crumbs">
        <span>workspace</span>
        <span className="sep">/</span>
        {view === 'console' ? (
          <>
            <span style={{cursor:'pointer', textDecoration:'underline', textDecorationStyle:'dotted', textUnderlineOffset:'3px'}} onClick={onBackToProjects}>{project.workspace}</span>
            <span className="sep">/</span>
            <span className="cur">{project.name}</span>
          </>
        ) : (
          <>
            <span>{project.workspace}</span>
            <span className="sep">/</span>
            <span className="cur">{project.name}</span>
          </>
        )}
      </div>
      <div className="hdr-spacer" />
      <div className={`hdr-run ${runState}`}>
        <span className="dot" />
        <span>RUN · {label}</span>
      </div>
      {view === 'console' && runState === 'idle' && (
        <button className="hdr-btn primary" onClick={onRun}>
          ▶ 启动 Pipeline <span className="kbd">⌘↵</span>
        </button>
      )}
      {view === 'console' && runState === 'running' && (
        <button className="hdr-btn" onClick={onReset}>■ 中断</button>
      )}
      {view === 'console' && runState === 'done' && (
        <button className="hdr-btn" onClick={onReset}>↻ 重置</button>
      )}
    </header>
  );
}

// ─── Left rail — agent list ─────────────────────────────────────────────
function AgentRail({ agents, activeId, runningId, completed, onSelect }) {
  return (
    <aside className="rail">
      <div className="rail-section">
        <h4>Agents <span className="count">{agents.length}</span></h4>
        {agents.map((a) => {
          const isActive = a.id === activeId;
          const isRunning = a.id === runningId;
          const isDone = completed.has(a.id);
          const status = isRunning ? 'running' : isDone ? 'done' : 'ready';
          return (
            <div
              key={a.id}
              className={`agent-card ${isActive ? 'active' : ''} ${isRunning ? 'running' : ''}`}
              onClick={() => onSelect(a.id)}
            >
              <div className="agent-card-row">
                <AgentGlyph agent={a} />
                <span className="agent-name">{a.name}</span>
                <span className={`agent-status ${status}`}>
                  {status === 'running' ? '运行中' : status === 'done' ? '已完成' : '就绪'}
                </span>
              </div>
              <div className="agent-meta">
                <span><b>{a.skills}</b> skills</span>
                <span><b>{a.runs}</b> runs</span>
                <span style={{ flex: 1, textAlign: 'right' }}>{a.code}</span>
              </div>
            </div>
          );
        })}
      </div>

      <div className="rail-spacer" />

      <div className="rail-runs">
        <h4 style={{ margin: '0 0 8px', color: 'var(--muted)', fontSize: 10, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
          Recent runs
        </h4>
        <div className="run-item"><span>#2891 反馈系统</span><span className="ok">✓ 4m12s</span></div>
        <div className="run-item"><span>#2890 优惠券中台</span><span className="ok">✓ 6m48s</span></div>
        <div className="run-item"><span>#2889 客服工作台</span><span>↻ 重启</span></div>
        <div className="run-item"><span>#2888 数据看板</span><span className="ok">✓ 3m52s</span></div>
      </div>
    </aside>
  );
}

// ─── Workflow strip ─────────────────────────────────────────────────────
function Workflow({ agents, runningId, completed, activeId, onSelect, runState }) {
  return (
    <section className="wf">
      <div className="wf-bg" />
      <div className="wf-head">
        <h3>Pipeline · 实时流转</h3>
        <div className="legend">
          <span><i style={{ background: 'var(--muted)' }} /> idle</span>
          <span><i style={{ background: 'var(--accent)' }} /> running</span>
          <span><i style={{ background: 'var(--green)' }} /> done</span>
        </div>
      </div>

      <div className="wf-canvas">
        {agents.map((a, i) => {
          const isRunning = a.id === runningId;
          const isDone = completed.has(a.id);
          const isActive = a.id === activeId;
          const cls = isRunning ? 'running' : isDone ? 'done' : (runState === 'idle' ? 'idle' : 'idle');
          const nextDone = i < agents.length - 1
            && (completed.has(a.id) || isRunning)
            && (completed.has(agents[i + 1].id) || agents[i + 1].id === runningId);
          const edgeFlowing = i < agents.length - 1
            && completed.has(a.id)
            && agents[i + 1].id === runningId;
          const edgeDone = i < agents.length - 1
            && completed.has(a.id) && completed.has(agents[i + 1].id);
          return (
            <React.Fragment key={a.id}>
              <div
                className={`wf-node ${cls} ${isActive ? 'active' : ''}`}
                onClick={() => onSelect(a.id)}
              >
                <div className="wf-node-head">
                  <AgentGlyph agent={a} />
                  <span className="wf-node-name">{a.name.replace(' Agent', '')}</span>
                  <span className="wf-node-code">{a.code}</span>
                </div>
                <div className="wf-node-row">
                  <span>状态</span>
                  <span className="v">
                    {isRunning ? '推理中…' : isDone ? '✓ 输出已就绪' : '待启动'}
                  </span>
                </div>
                <div className="wf-node-row">
                  <span>输出</span>
                  <span className="v">
                    {a.id === 'req' ? 'requirements.md'
                      : a.id === 'prd' ? 'prd.v0.1.md'
                      : 'prototype.html'}
                  </span>
                </div>
              </div>
              {i < agents.length - 1 && (
                <div className={`wf-edge ${edgeFlowing ? 'flow' : ''} ${edgeDone ? 'done' : ''}`}>
                  {edgeFlowing && <span className="pulse" />}
                </div>
              )}
            </React.Fragment>
          );
        })}
      </div>
    </section>
  );
}

// ─── Chat ───────────────────────────────────────────────────────────────
function Chat({ agent, messages, draft, setDraft, onSend, isAgentTyping, onPresetSelect, presetActive }) {
  const bodyRef = useRef(null);
  const taRef = useRef(null);

  useEffect(() => {
    if (bodyRef.current) {
      bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
    }
  }, [messages, isAgentTyping]);

  useEffect(() => {
    if (taRef.current) {
      taRef.current.style.height = 'auto';
      taRef.current.style.height = Math.min(140, taRef.current.scrollHeight) + 'px';
    }
  }, [draft]);

  const onKey = (e) => {
    if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
      e.preventDefault();
      onSend();
    }
  };

  return (
    <section className="chat">
      <div className="chat-head">
        <AgentGlyph agent={agent} />
        <span className="who">{agent.name}</span>
        <span className={`status-pill ${isAgentTyping ? 'running' : ''}`}>
          {isAgentTyping ? 'Thinking' : 'Ready'}
        </span>
        <div className="chat-head-spacer" />
        <span className="meta-stat">role · <b>{agent.role}</b></span>
        <span className="meta-stat">skills · <b>{agent.skills}</b></span>
      </div>

      <div className="chat-body" ref={bodyRef}>
        {messages.map((m, i) => (
          <div key={i} className={`msg ${m.role} ${m.kind || ''}`}>
            <div className="who-line">
              {m.role === 'agent' && (
                <span className="glyph" style={{ background: agent.color }}>
                  {agent.code.split('-')[0]}
                </span>
              )}
              <span>{m.role === 'user' ? '你' : (m.kind === 'tool' ? 'TOOL CALL' : m.kind === 'memory' ? 'MEMORY WRITE' : agent.name)}</span>
              <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--muted)' }}>
                {m.t || ''}
              </span>
            </div>
            <div className="body">{m.text}</div>
          </div>
        ))}
        {isAgentTyping && (
          <div className="msg" style={{ alignSelf: 'flex-start' }}>
            <div className="who-line">
              <span className="glyph" style={{ background: agent.color }}>
                {agent.code.split('-')[0]}
              </span>
              <span>{agent.name}</span>
            </div>
            <div className="typing">
              <i /><i /><i />
            </div>
          </div>
        )}
      </div>

      <div className="chat-input-wrap">
        <div className="chat-input">
          <textarea
            ref={taRef}
            placeholder={`向 ${agent.name} 输入需求或指令…`}
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onKeyDown={onKey}
          />
          <div className="chat-input-toolbar">
            <div className="chips">
              <span className="chip" onClick={() => onPresetSelect('feedback')}>
                ↦ 反馈管理系统
              </span>
              <span className="chip" onClick={() => onPresetSelect('coupon')}>
                ↦ 优惠券中台
              </span>
              <span className="chip" onClick={() => onPresetSelect('dashboard')}>
                ↦ 数据看板
              </span>
            </div>
            <button
              className="hdr-btn primary"
              onClick={onSend}
              disabled={!draft.trim() || isAgentTyping}
            >
              发送 <span className="kbd">⌘↵</span>
            </button>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─── Memory inspector ───────────────────────────────────────────────────
function MemoryInspector({ layers, writingLayerId, recentWrites }) {
  const [expanded, setExpanded] = useState('L1');
  return (
    <div className="insp-body">
      <div className="mem-intro">
        Hermes 框架将记忆划分为 <b>四级</b>：从瞬时上下文到跨项目的长期沉淀。
        每一级有不同的容量、写入频率与生命周期，Agent 推理时会按需召回相应层级。
      </div>
      {layers.map((l) => {
        const isWriting = writingLayerId === l.id;
        const fillPct = Math.min(100, (l.fill / l.capacity) * 100);
        const isOpen = expanded === l.id;
        const fresh = recentWrites.filter((w) => w.layerId === l.id);
        return (
          <div key={l.id} className={`mem-layer ${isWriting ? 'writing' : ''}`}>
            <div className="mem-layer-head" onClick={() => setExpanded(isOpen ? null : l.id)}>
              <div className="mem-layer-row">
                <span className="mem-id">{l.id}</span>
                <span className="mem-name">{l.name}</span>
                <span className="mem-en">{l.en}</span>
              </div>
              <div className="mem-bar">
                <div className="mem-bar-fill" style={{ width: `${fillPct}%` }} />
              </div>
              <div className="mem-stats">
                <span>使用 <span className="num">{l.fill.toLocaleString()}</span> / {l.capacity.toLocaleString()} {l.unit}</span>
                <span>{fillPct.toFixed(1)}%</span>
              </div>
            </div>
            {isOpen && (
              <div className="mem-layer-detail">
                <div className="mem-desc">{l.desc}</div>
                <div className="mem-decay">decay · {l.decay}</div>
                <div className="mem-items">
                  {fresh.slice(-2).reverse().map((w, i) => (
                    <div key={'new' + i} className="mem-item">
                      <span>{w.t}</span>
                      <span className="k">{w.s}</span>
                      <span className="v">{w.d}<span className="new">NEW</span></span>
                    </div>
                  ))}
                  {l.items.map((it, i) => (
                    <div key={i} className="mem-item">
                      <span>{it.t}</span>
                      <span className="k">{it.s}</span>
                      <span className="v">{it.d}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

// ─── Skills inspector ───────────────────────────────────────────────────
function SkillsInspector({ agentId, skills, flashSkill }) {
  const max = Math.max(...skills.flatMap(s => s.trend), 1);
  return (
    <div className="insp-body">
      <div className="skill-intro">
        每次调用都会更新 Skill 的<b style={{ color: 'var(--ink-2)' }}> 经验向量</b>。
        高频被调用的 Skill 准确率持续提升，并在 L3 长期记忆中沉淀为可复用模式。
      </div>
      {skills.length === 0 && (
        <div className="skill-empty">该 Agent 暂未注册 Skill</div>
      )}
      {skills.map((s, i) => {
        const isFlash = flashSkill === s.name;
        return (
          <div key={s.name} className={`skill ${isFlash ? 'flash' : ''}`}>
            <div className="skill-row">
              <span className="skill-name">{s.name}</span>
              <span className="skill-inv">{s.invocations.toLocaleString()} 次</span>
            </div>
            <div className="skill-row-2">
              <span className="skill-level" title={`Lv ${s.level}`}>
                {[1,2,3,4,5].map((n) => (
                  <i key={n} className={n <= s.level ? 'on' : ''} />
                ))}
              </span>
              <div className="skill-spark">
                {s.trend.map((v, j) => (
                  <i key={j}
                     className={j === s.trend.length - 1 ? 'last' : ''}
                     style={{ height: `${(v / max) * 100}%` }} />
                ))}
              </div>
              <span className="skill-delta">{s.delta}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ─── Inspector tabs container ───────────────────────────────────────────
function Inspector({ tab, setTab, layers, writingLayerId, recentWrites, agentId, skills, flashSkill }) {
  return (
    <aside className="inspector">
      <div className="insp-tabs">
        <button className={`insp-tab ${tab === 'memory' ? 'active' : ''}`} onClick={() => setTab('memory')}>
          多层记忆 <span className="badge">{layers.length}</span>
        </button>
        <button className={`insp-tab ${tab === 'skills' ? 'active' : ''}`} onClick={() => setTab('skills')}>
          Skills <span className="badge">{skills.length}</span>
        </button>
      </div>
      {tab === 'memory' ? (
        <MemoryInspector layers={layers} writingLayerId={writingLayerId} recentWrites={recentWrites} />
      ) : (
        <SkillsInspector agentId={agentId} skills={skills} flashSkill={flashSkill} />
      )}
    </aside>
  );
}

Object.assign(window, {
  Header, AgentRail, Workflow, Chat, Inspector, AgentGlyph,
});
