/**
 * `TodoWrite` tool —— LLM 的"工作记忆" TODO 清单（CC 模式）。
 *
 * 用法：LLM 在 Plan mode / 复杂多步任务时调 TodoWrite([{id, text, completed}, ...])
 * 整个数组**完整重写**当前 TODO 状态。下次调用时 LLM 重新提交完整列表，标 completed=true
 * 表示该项已做完。
 *
 * 不持久化（每次 LLM 重写就是当前状态；不存数据库）；前端检测 output.todos 数组
 * 渲染成 checklist。
 */

import { Injectable } from '@nestjs/common';
import type { AgentTool, ToolDescriptor, ToolInvocation, ToolResult } from './tool.types';

@Injectable()
export class TodoWriteTool implements AgentTool {
  readonly descriptor: ToolDescriptor = {
    name: 'TodoWrite',
    description:
      '维护当前对话的 **TODO 清单**（多步任务里跟踪进度用）。' +
      '调用时**整个数组完整重写**：每次提交全部 todos，标 completed=true 表示该项已做完。' +
      '典型场景：用户问"帮我做 5 件事" → 第一次 TodoWrite 列 5 项 → 做完第 1 项再 TodoWrite 标第 1 项 completed → 以此类推。' +
      '不用于持久化项目计划（那是 TaskCreate）；只是 LLM 工作记忆。',
    inputSchema: {
      todos: {
        type: 'string',
        required: true,
        description:
          'JSON 数组字符串：[{"id":"1","text":"读 package.json","completed":true},{"id":"2","text":"找 bug","completed":false}]。每项需 id/text/completed 三字段。',
      },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: false,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const raw = String(inv.input.todos ?? '').trim();
    if (!raw) return { ok: false, errorMessage: 'todos 不能为空' };
    let parsed: Array<{ id: string; text: string; completed: boolean }>;
    try {
      parsed = JSON.parse(raw);
    } catch (err) {
      return { ok: false, errorMessage: `todos 不是合法 JSON：${(err as Error).message}` };
    }
    if (!Array.isArray(parsed)) {
      return { ok: false, errorMessage: 'todos 必须是数组' };
    }
    // 校验 + 归一化
    const todos: Array<{ id: string; text: string; completed: boolean }> = [];
    for (const item of parsed) {
      if (!item || typeof item !== 'object') continue;
      const id = String((item as Record<string, unknown>).id ?? '').trim();
      const text = String((item as Record<string, unknown>).text ?? '').trim();
      const completed = Boolean((item as Record<string, unknown>).completed);
      if (!id || !text) continue;
      todos.push({ id, text, completed });
    }
    if (todos.length === 0) {
      return { ok: false, errorMessage: 'todos 解析后为空（确保每项含 id/text 非空字符串）' };
    }
    const done = todos.filter((t) => t.completed).length;
    return {
      ok: true,
      output: {
        todos,
        total: todos.length,
        completed: done,
        pending: todos.length - done,
      },
    };
  }
}
