'use client';

import { useState } from 'react';
import { ChevronDown, ChevronRight } from 'lucide-react';

/**
 * 助手消息里的**轨迹行** —— 现在只剩「思考」一种，外加工具的中文说法表。
 *
 * ═══ 「执行过程」那一整套 2026-08-19 已删 ═══════════════════════════
 * 产品定：「调用工具和执行过程去掉，用户不需要知道」。删掉的是
 *   · `StepRow`  —— 正文里那行「出分配方案 `propose_assignment`」（前半产品说法、后半函数名）
 *   · `StepTrace` —— 消息末尾那行「执行过程 · 4 步 出分配方案 → 摆选项按钮 → …」
 * 主管要判断的是"这一版分得对不对"，⛔ 不是"它走了哪条代码路径"；而「摆选项按钮」
 * 这种渲染动作被列出来，讲的是装置内部怎么跑的。
 *
 * ═══ ⚠️ 但下面这件事没有失效，只是换了地方 ═══════════════════════
 * 🔴 「模型到底调没调工具」是这条生产线**最贵的一类问题**。2026-08-13 实测吃过一次：
 *   主管点了「只圈电商平台那 251 人」，助手回了一整份确认单式的汇报
 *   （251 人 / 98 条落到 33 位客服 / 17 回专属 / 81 补空 / 153 待分配），
 *   数字彼此自洽、读起来毫无破绽 —— 但 `propose_assignment` 一次都没跑，
 *   整段是照着提示词里那个三段模板**填出来的**。
 * ⇒ 现在这件事**在服务端查**：`agent_invocations.output.toolCalls / steps`
 *   （每一步「讲了多少字 + 调了哪些工具」，见 `assistant-invocation.ts` 的 `stepShapes`）。
 *   界面上的替代物只有一个：`toolMeta().running` 那句等待文案 —— 它说的是**动作**
 *   （「正在挑人、排客服，出分配方案」），⛔ 不是工具名。
 * ⚠️ 裸台 `/assistant-lab` 仍旧原样展示全部步骤，但它**自己写了一份**、⛔ 不引这里 ——
 *   改这个文件不会让裸台跟着变，反过来也一样。
 */

/**
 * 工具 → 中文说法。**凡是注册进 MCP / 助手的工具都要在这里有一条。**
 *
 * ⚠️ 未映射时**显示原始英文名**，⛔ 不显示空白 —— 漏配一个要能一眼看见。
 *   （曾经漏过四个，兜底文案直接把 `get_cohort_attributes` 摆给了主管看。）
 */
const TOOL_META: Record<string, { label: string; running: string }> = {
  find_patient: { label: '查找患者', running: '正在查找患者' },
  get_patient_overview: { label: '读取患者概览', running: '正在读取患者概览' },
  get_persona: { label: '读取患者画像', running: '正在读取患者画像' },
  get_facts: { label: '读取关键事实', running: '正在读取关键事实' },
  get_recall_plan: { label: '读取召回计划', running: '正在读取召回计划' },
  list_recall_queue: { label: '检索召回队列', running: '正在检索召回队列' },
  recall_queue_stats: { label: '统计召回池', running: '正在统计召回池' },
  get_current_user: { label: '确认身份', running: '正在确认你的身份与权限' },
  get_agents: { label: '查在岗客服', running: '正在查在岗客服与在手负载' },
  propose_assignment: { label: '出分配方案', running: '正在挑人、排客服，出分配方案' },
  list_assignment_batches: { label: '查历史批次', running: '正在查你分过的批次' },
  get_assignment_detail: { label: '查批次详情', running: '正在查这批的执行情况' },
  explain_assignment: { label: '解释为什么是他', running: '正在查这个人为什么被选进来' },
  get_cohort_attributes: { label: '看这批人构成', running: '正在看这批人里各类有多少' },
  edit_assignment_sheet: { label: '改确认单', running: '正在按你说的改确认单' },
  // ⚠️ 查的是**眼前那张还没确认的**单子(草稿态,由浏览器随请求捎给服务端)——
  //   与 `get_assignment_detail`(已经分下去的那批)⛔ 不是一回事,标签也别写像
  get_current_sheet: { label: '看当前确认单', running: '正在看这张单现在什么样' },
  revoke_assignment: { label: '撤销批次', running: '正在撤销这批' },
  render_artifact: { label: '出图表', running: '正在画图' },
  // 取一篇做法(pull 式加载,见服务端 assistant-playbooks):不查库不改数据
  open_playbook: { label: '取做法', running: '正在取这类活的做法' },
  // ── 调整各客服在手的单(2026-08-20)——与上面确认单那三件一一对应 ──
  // ⚠️ 说的是**动作**,⛔ 不是工具名:漏配的话兜底文案会把 `propose_rearrange`
  //   这串英文直接摆给主管看(2026-08-20 走查抓到的就是这个)。
  propose_rearrange: { label: '出调整单', running: '正在把各客服手上的单摆出来' },
  edit_rearrange_sheet: { label: '改调整单', running: '正在按你说的改调整单' },
  // ── 纯位置标记，不查库不写库（见 assistant.service 的 place_*）──
  show_sheet: { label: '摆确认单卡片', running: '正在摆确认单' },
  show_rearrange: { label: '摆调整单卡片', running: '正在摆调整单' },
  show_guidance: { label: '摆选项按钮', running: '正在摆选项按钮' },
};

/** 给测试用 —— ⚠️ 只读导出,⛔ 别在运行时拿它当映射表(那是 `toolMeta` 的活) */
export const TOOL_META_KEYS = Object.keys(TOOL_META);

export function toolMeta(tool: string) {
  return TOOL_META[tool] ?? { label: tool, running: `正在调用 ${tool}` };
}

/** 展示用的长度上限 —— ⚠️ 与历史回传那份（`HISTORY_CAP`）**不是同一件事**，别去对齐：
 *  那边是省 token，这边是省版面，超出的部分靠滚动看，⛔ 不截断丢失。 */
// ⚠️ `max-h-56 overflow-auto` **不许动**:超出的部分靠滚动看,⛔ 不截断丢失。
//   2026-08-15 只改了外观:细边 + 更淡的底(对齐 Claude Code 那种"有框的浅盒")。
const BOX =
  'max-h-56 overflow-auto rounded-md border border-slate-200/80 bg-slate-50/60 px-2.5 py-2';
const MONO = 'whitespace-pre-wrap break-all font-mono text-[10.5px] leading-[1.6] text-slate-600';

/**
 * ⭐ **一条可折叠的轨迹行** —— 思考和工具调用共用的唯一原语。
 *
 * 为什么合成一个：它们在消息里**交错出现**，视觉必须同源，否则同一串时序读起来
 * 像两套东西。⇒ 一行标签 + 可展开的正文；差别只在标签和展开的内容。
 * ⚠️ 一律**默认收起**：这是脚注不是内容，主管要读的是结论。
 * ⛔ 别给其中一种单独加边框/底色 —— 那会把"谁更重要"的暗示塞进纯记录里。
 */
function TraceRow({
  label,
  tag,
  children,
}: {
  label: string;
  /** 灰色小字：思考字数 —— 流式期间它在长，是唯一能看出"还在想"的信号 */
  tag?: string;
  children?: React.ReactNode;
}) {
  const [open, setOpen] = useState(false);
  return (
    // ⭐ **无分隔线**(2026-08-15):一串轨迹行本来就是一串,横线把它切成了好几块小卡片。
    //   ⚠️ 行与行靠**留白**分开,⛔ 别再加回 border-t。
    <div>
      <button
        type="button"
        onClick={() => setOpen((v) => !v)}
        /**
         * ⭐ **文字顶到最左，箭头跟在后面**（2026-08-15）。
         *
         * 箭头原来在最前面，把这一行整体往右推了 18px —— 于是每一行轨迹都比它下面的
         * 正文缩进一截，读起来像是正文的子项，而它们本来是同一级的。
         * ⚠️ `-mx-2 px-2`：视觉左沿落在 0（与正文对齐），而悬停底色仍向两侧各溢出 8px，
         *   点击热区不至于紧贴文字。⛔ 别改成 `px-0`：那样悬停块会贴着字边，很局促。
         */
        className="-mx-2 flex w-full items-center gap-1.5 rounded-md px-2 py-1 text-left transition-colors hover:bg-slate-50"
      >
        <span className="text-[12px] text-slate-500">{label}</span>
        {tag && <span className="truncate font-mono text-[10.5px] text-slate-400">{tag}</span>}
        {open ? (
          <ChevronDown className="size-3 shrink-0 text-slate-400" />
        ) : (
          <ChevronRight className="size-3 shrink-0 text-slate-400" />
        )}
      </button>
      {/* ⚠️ 箭头挪到文字后面之后，展开内容与 label 左沿**天然对齐**（都落在 0）——
          ⛔ 别再加 `pl-*` 去"缩进一下"：那正是刚拆掉的那种错位。 */}
      {open && children && <div className="space-y-1 pb-2">{children}</div>}
    </div>
  );
}

/**
 * ⛔ **`StepRow`（一次工具调用的灰行）与 `StepTrace`（执行过程 · N 步）已删**
 *   （2026-08-19 产品定：「调用工具和执行过程去掉，用户不需要知道」）。
 *
 *   删的是**渲染**，⛔ 不是可核查性 —— 上面那段"为什么要有"讲的事仍然成立，只是换了地方：
 *     · 「正在出分配方案…」等待文案还在（`toolMeta().running`，说的是动作不是工具名）；
 *     · 每一步的形状落在 `agent_invocations.output.steps`（服务端留痕，可回查）；
 *     · 裸台 `/assistant-lab` 有自己那一份执行过程（⚠️ 它**不引这里**，别改这边指望那边跟着变）。
 *   ⛔ 别把它们留成"没人用的导出" —— 一段永远不渲染的组件读起来像"这个功能还在"。
 *   要放回来：改 `assistant-chat` 里 `rest` 那一处过滤，再把组件写回来。
 */

/**
 * 模型的思考。⚠️ 标签上带**字数**：流式期间它在长，字数是唯一能看出"还在想"的信号。
 * ⛔ 别自动展开 —— 实测单轮能到三千多字，摊开会把正文淹掉。
 */
export function ReasoningRow({ text }: { text: string }) {
  return (
    <TraceRow label="思考" tag={`${text.length} 字`}>
      <div className={BOX}>
        <div className={MONO}>{text}</div>
      </div>
    </TraceRow>
  );
}
