import Image from "next/image";
import { ToolPositionMap } from "./tool-position-map";

type Section = {
	id: string;
	no: string;
	title: string;
	summary: string;
	image?: string;
	doc?: string;
	points: string[];
	code: string[];
	decision: string;
};

const assetPrefix = "/doc-assets/technical";
const architectureImage = `${assetPrefix}/00-zk-data-agent-architecture.png`;

const sections: Section[] = [
	{
		id: "base",
		no: "01",
		title: "基座 Runtime",
		summary:
			"基座把本地工程 Agent 的循环执行能力，包装成多人可使用、可观测、可沉淀、可扩展的 Web 工作台。",
		image: `${assetPrefix}/01-base-runtime.png`,
		doc: "/doc/01-base-runtime",
		points: [
			"基于 LocalCodingAgent、OpenAI-compatible 模型调用、Tool Runtime、Session Workspace 和 Skill System 组合而成。",
			"解决个人脚本和一次性对话难以团队复用的问题：流程、工具、知识、产物都挂到同一个会话空间。",
			"在 product-data、online-mining-v2、标签大师、飞书在线文档转换等场景中验证了基座的通用承载能力。",
		],
		code: [
			"backend/api/server.py",
			"src/agent_runtime.py",
			"src/agent_prompting.py",
			"src/openai_compat.py",
		],
		decision:
			"基座只承载跨业务稳定能力；变化快的业务判断、流程经验和格式转换下沉到 Skill。",
	},
	{
		id: "loop",
		no: "02",
		title: "Agent Loop",
		summary:
			"模型不是只回答一次，而是在多轮循环里阅读上下文、请求工具、观察结果、继续判断。",
		image: `${assetPrefix}/02-agent-loop.png`,
		doc: "/doc/02-agent-loop",
		points: [
			"模型是否返回 tool_calls 由模型基于 messages、工具描述、Skill 和上下文自行决定。",
			"工具结果写回 session，成为下一轮模型判断的输入。",
			"review gate 不是特殊流程，而是一次运行自然暂停，等待用户下一轮确认后 resume。",
		],
		code: [
			"LocalCodingAgent.run",
			"LocalCodingAgent.resume",
			"_run_prompt",
			"_query_model",
		],
		decision:
			"复杂任务需要执行后再判断；把工具观察结果纳入下一轮上下文，比一次性输出更可靠。",
	},
	{
		id: "tools",
		no: "03",
		title: "工具体系",
		summary:
			"工具由 Tool spec 和 handler 两部分组成：spec 给模型选择，handler 在后端执行。",
		image: `${assetPrefix}/03-tools.png`,
		doc: "/doc/03-tools",
		points: [
			"Tool registry 汇总文件、执行、搜索、Skill、data_agent、MCP 等能力。",
			"模型只看到 name、description 和参数 schema，看不到 handler 实现。",
			"结构化分析和复杂文件写入优先走 python_exec；write_file 只适合小文件。",
		],
		code: [
			"src/agent_tools.py",
			"src/agent_tool_specs/files.py",
			"src/agent_tool_specs/execution.py",
		],
		decision:
			"模型负责选择能力，代码负责稳定执行能力；两者分开后才能做权限、取消、路径和审计。",
	},
	{
		id: "skills",
		no: "04",
		title: "Skill 体系",
		summary:
			"Skill 是能力包，包含流程协议、领域知识、确定性脚本、样例和维护说明。",
		image: `${assetPrefix}/04-skills.png`,
		doc: "/doc/04-skills",
		points: [
			"SKILL.md 定义触发场景、执行流程、review 边界和产物约定。",
			"knowledge/ 放业务定义和边界经验，scripts/ 放稳定脚本。",
			"项目级 skills/ 可以通过页面更新机制刷新到模型可见能力列表。",
		],
		code: [
			"src/bundled_skills.py",
			"skills/*/SKILL.md",
			"frontend Skills 面板",
		],
		decision:
			"团队经验只有形成可安装、可更新、可阅读、可执行的目录结构，才方便多人复用和维护。",
	},
	{
		id: "workspace",
		no: "05",
		title: "工作区、运行态和记忆",
		summary:
			"每个账号和会话都有独立空间，运行过程通过事件流展示，交互结束后异步整理记忆。",
		image: `${assetPrefix}/05-workspace-memory-observability.png`,
		doc: "/doc/05-workspace-memory-observability",
		points: [
			"session/input 放输入材料，session/scratchpad 放中间过程，session/output 放最终产物。",
			"右侧活动区和摘要行来自运行态事件流，刷新后通过会话记录恢复。",
			"用户记忆和 Skill 记忆分开保存，只在需要的上下文中注入。",
		],
		code: [
			".port_sessions/accounts/{account}/sessions/{session}",
			"RunStateStore",
			"src/personal_memory.py",
		],
		decision: "多人使用时，隔离、恢复、取消、观测和产物管理比单次回答更重要。",
	},
	{
		id: "subagents",
		no: "11",
		title: "子 Agent 边界",
		summary:
			"子 Agent 是主 Agent 派出的隔离工作单元，适合长耗时、可并行、读多写少、边界清晰的子任务。",
		doc: "/doc/11-subagents",
		points: [
			"默认仍然是主 Agent + Skill + Tool；子 Agent 不是复杂任务的默认答案。",
			"适合多个 rid、多个文件、多个候选方向并行探索，或让 verification 独立验收。",
			"不适合强共享上下文、强顺序依赖、多个 Agent 同时写同一份最终产物的任务。",
		],
		code: [
			"src/agent_tools.py",
			"src/agent_prompting.py",
			"src/builtin_agents.py",
			"src/agent_runtime.py",
		],
		decision:
			"子 Agent 负责观察和验证，主 Agent 负责用户上下文、最终决策和产物写入。",
	},
	{
		id: "runtime-guidance",
		no: "12",
		title: "运行中输入队列",
		summary:
			"运行中的用户输入先入队，只有用户显式引导时才在 Agent loop 安全边界注入当前 run。",
		doc: "/doc/12-runtime-guidance-queue",
		points: [
			"display_messages、model_messages、run_events 和 input_queue 分离，避免刷新、compact 和多会话切换互相污染。",
			"运行中 Enter 写入队列，不创建新 run，不取消当前 run。",
			"引导消息以 hidden runtime guidance 注入模型，不作为普通用户历史展示。",
		],
		code: [
			"src/session_store.py",
			"src/run_state_store.py",
			"src/agent_runtime.py",
			"frontend input queue chips",
		],
		decision:
			"UI、模型和持久化不能共享同一份 mutable messages；运行中交互必须事件化、可恢复、可取消。",
	},
];

const skillSections: Section[] = [
	{
		id: "product",
		no: "06",
		title: "product-data",
		summary:
			"从产品定义、标签边界、样例 query 或 badcase 出发，生成标准 canonical records 并导出多种数据格式。",
		image: `${assetPrefix}/06-product-data.png`,
		doc: "/doc/06-product-data",
		points: [
			"先抽取 generation goal，再让用户 review 标签、complex、覆盖范围和排除边界。",
			"确认后生成 generation plan，再确认数量、轮次、路径和导出目标。",
			"dataset draft text 通过 scripts 转成 canonical records，再导出 records.jsonl、流转 CSV、训练 JSONL、评测 CSV。",
		],
		code: [
			"skills/product-data/SKILL.md",
			"skills/product-data/scripts/*",
			"canonical_record_v1",
		],
		decision:
			"数据生成质量不只取决于模型文本，还取决于格式规范、校验脚本和 review 门禁。",
	},
	{
		id: "online",
		no: "07",
		title: "online-mining-v2",
		summary:
			"基于 ELK 线上日志挖掘候选样本，支持策略 review、抽样分析，以及直接转换为标准数据。",
		image: `${assetPrefix}/07-online-mining-v2.png`,
		doc: "/doc/07-online-mining-v2",
		points: [
			"从需求、badcase 或示例 query 分析查询策略。",
			"通过 ELK 表获取 req_id、session、模型 prompt、模型输出、domain 等字段。",
			"候选结果先抽样 review，再决定直接转样本还是进入 product-data 补数链路。",
		],
		code: [
			"skills/online-mining-v2/SKILL.md",
			"skills/elk-fetch/",
			"build_online_records.py",
		],
		decision: "线上挖掘不是一次查询，策略需要多轮调整，候选质量需要人工确认。",
	},
	{
		id: "label",
		no: "08",
		title: "标签大师",
		summary:
			"把标签定义、复杂度、多指令、自动任务和边界经验组织为可检索、可解释的知识体系。",
		image: `${assetPrefix}/08-label-master.png`,
		doc: "/doc/08-label-master",
		points: [
			"复杂度、标签、多指令、自动任务是不同判断维度。",
			"标签知识通过目录、索引、边界卡片和 manifest 组织。",
			"输出需要同时满足标签合法性、输出形态和 complex 独立字段要求。",
		],
		code: [
			"skills/label-master/knowledge",
			"build_label_manifest.py",
			"validate_label_output.py",
		],
		decision:
			"标签判断需要逐步分析和引用知识，而不是把所有定义塞进一次模型输入。",
	},
	{
		id: "external",
		no: "09",
		title: "外部系统 Skill",
		summary:
			"ELK、SQL、模型迭代、飞书文档等外部能力通过 Skill 包方式接入平台。",
		image: `${assetPrefix}/09-external-skills.png`,
		doc: "/doc/09-external-skills",
		points: [
			"SKILL.md 描述外部系统能力边界和使用流程。",
			"scripts/ 负责调用外部 API、鉴权、查询和格式转换。",
			"最终结果统一回到当前会话 output，而不是散落在项目根目录。",
		],
		code: [
			"skills/elk-fetch",
			"skills/data-factory-sql",
			"skills/model-iteration",
			"Feishu MCP 转在线文档",
		],
		decision: "外部系统能力变化快，适合跟随 Skill 独立迭代，避免侵入基座。",
	},
];

const exampleSessions = [
	{
		title: "product-data",
		description:
			"数据生成链路：目标抽取、计划确认、分批生成、canonical records 和训练/评测格式导出。",
		links: [
			"http://10.189.47.6/session/__LOCALID_ZgwXdfP",
			"http://10.189.47.6/session/__LOCALID_QOecDTu",
		],
	},
	{
		title: "标签大师",
		description:
			"标签知识判断链路：复杂度、多指令、自动任务、function/tag 输出形态和边界知识引用。",
		links: [
			"http://10.189.47.6/session/__LOCALID_ji5lCfb",
			"http://10.189.47.6/session/__LOCALID_Z22r3pn",
			"http://10.189.47.6/session/__LOCALID_jsu7aIX",
			"http://10.189.47.6/session/__LOCALID_WjULYPt",
			"http://10.189.47.6/session/__LOCALID_YJyPnF7",
		],
	},
	{
		title: "标签大师 + online-mining",
		description:
			"组合链路：先用线上日志定位样本，再结合标签知识做判断、整理和格式转换。",
		links: ["http://10.189.47.6/session/__LOCALID_OLKxKnf"],
	},
	{
		title: "online-mining",
		description:
			"线上挖掘链路：查询策略、ELK 字段探索、候选样本抽样 review 和标准数据沉淀。",
		links: [
			"http://10.189.47.6/session/__LOCALID_BnxMLqn",
			"http://10.189.47.6/session/__LOCALID_xZRilR5",
			"http://10.189.47.6/session/__LOCALID_CBy2JB5",
		],
	},
];

function SectionBlock({ section }: { section: Section }) {
	return (
		<section className="project-doc-section" id={section.id}>
			<div className="project-doc-section-head">
				<span>{section.no}</span>
				<div>
					<h2>{section.title}</h2>
					<p>{section.summary}</p>
				</div>
			</div>
			{section.image ? (
				<a
					className="project-doc-figure"
					href={section.image}
					rel="noopener"
					target="_blank"
				>
					<Image
						alt={section.title}
						height={900}
						priority={section.id === "base"}
						src={section.image}
						width={1600}
					/>
				</a>
			) : null}
			<div className="project-doc-grid">
				<div>
					<h3>关键机制</h3>
					{section.points.map((point) => (
						<p className="project-doc-point" key={point}>
							{point}
						</p>
					))}
				</div>
				<div>
					<h3>代码入口</h3>
					{section.code.map((item) => (
						<code key={item}>{item}</code>
					))}
					{section.doc ? (
						<a className="project-doc-link" href={section.doc} rel="noopener">
							查看详细文档
						</a>
					) : null}
				</div>
				<div>
					<h3>设计取舍</h3>
					<p>{section.decision}</p>
				</div>
			</div>
		</section>
	);
}

export default function DocPage() {
	return (
		<main className="project-doc-page">
			<header className="project-doc-hero">
				<nav className="project-doc-nav">
					<a href="/">ZK Data Agent</a>
					<div>
						<a href="#base">基座</a>
						<a href="#loop">Agent Loop</a>
						<a href="#subagents">子 Agent</a>
						<a href="#skills">Skill</a>
						<a href="#product">业务链路</a>
						<a href="#examples">示例 Session</a>
						<a href="#code-index">代码索引</a>
					</div>
				</nav>
				<div className="project-doc-hero-inner">
					<p className="project-doc-kicker">技术架构说明</p>
					<h1>ZK Data Agent</h1>
					<p>
						基于本地工程 Agent、工具调用、Skill
						能力包和会话工作区构建的团队工作台，用来把数据开发、线上挖掘、标签知识建设中的流程经验变成可复用能力。
					</p>
				</div>
			</header>

			<ToolPositionMap />

			<section className="project-doc-section" id="architecture">
				<div className="project-doc-section-head">
					<span>00</span>
					<div>
						<h2>ZK-Data-Agent 架构</h2>
						<p>
							基座是一个通用 Code Agent
							Loop；我们的工作不是重写这个闭环，而是在关键节点补上团队业务能力，让执行、业务上下文和流程沉淀进入同一套工作台。
						</p>
					</div>
				</div>
				<a
					className="project-doc-figure"
					href={architectureImage}
					rel="noopener"
					target="_blank"
				>
					<Image
						alt="ZK-Data-Agent 架构"
						height={900}
						priority
						src={architectureImage}
						width={1600}
					/>
				</a>
				<div className="project-doc-grid">
					<div>
						<h3>基座提供执行闭环</h3>
						<p>
							Code Agent
							负责把任务放进多轮循环：组装上下文、模型推理、调用工具、观察结果，再继续规划或完成。它让模型从一次回答变成可以持续执行的运行时。
						</p>
					</div>
					<div>
						<h3>增强层体现我们的工作</h3>
						<p>
							ZK-Data-Agent 在上下文、工具、产物和团队协作节点接入 Skill
							体系、Skill 热更新、用户记忆、Skill 记忆、portable
							scripts、会话工作区、活动流和管理后台。
						</p>
					</div>
					<div>
						<h3>效率来自工程化补齐</h3>
						<p>
							工具和工作区提升研发执行效率；Skill 与记忆提升业务嵌入深度；Git 化
							Skill、热更新和团队治理提升流程可复用度。
						</p>
					</div>
				</div>
			</section>

			{sections.map((section) => (
				<SectionBlock key={section.id} section={section} />
			))}

			{skillSections.map((section) => (
				<SectionBlock key={section.id} section={section} />
			))}

			<section className="project-doc-section" id="examples">
				<div className="project-doc-section-head">
					<span>E</span>
					<div>
						<h2>示例 Session</h2>
						<p>
							下面这些是真实跑过的会话，适合讲解时直接打开。它们展示的不是单次问答，而是
							Skill 如何在 Agent Loop
							中完成计划、工具调用、人工确认、产物生成和格式转换。
						</p>
					</div>
				</div>
				<div className="project-doc-session-grid">
					{exampleSessions.map((group) => (
						<div className="project-doc-session-card" key={group.title}>
							<h3>{group.title}</h3>
							<p>{group.description}</p>
							<div>
								{group.links.map((link, index) => (
									<a href={link} key={link} rel="noopener" target="_blank">
										<span>{String(index + 1).padStart(2, "0")}</span>
										{link.replace("http://10.189.47.6/session/", "")}
									</a>
								))}
							</div>
						</div>
					))}
				</div>
			</section>

			<section className="project-doc-section" id="code-index">
				<div className="project-doc-section-head">
					<span>I</span>
					<div>
						<h2>代码索引</h2>
						<p>
							后续排查或二次开发时，可以先按下面入口定位问题属于基座、工具、Skill、工作区还是记忆。
						</p>
					</div>
				</div>
				<div className="project-doc-index">
					<div>
						<h3>Runtime</h3>
						<code>backend/api/server.py</code>
						<code>src/agent_runtime.py</code>
						<code>src/openai_compat.py</code>
					</div>
					<div>
						<h3>Prompt / Tool</h3>
						<code>src/agent_prompting.py</code>
						<code>src/agent_tools.py</code>
						<code>src/agent_tool_specs/</code>
					</div>
					<div>
						<h3>Skill</h3>
						<code>src/bundled_skills.py</code>
						<code>skills/product-data/</code>
						<code>skills/label-master/</code>
					</div>
					<div>
						<h3>State</h3>
						<code>src/personal_memory.py</code>
						<code>.port_sessions/accounts/</code>
						<code>frontend/app/app/doc/page.tsx</code>
					</div>
				</div>
			</section>
		</main>
	);
}
