/**
 * Task* 工具集 —— LLM 创建 / 更新 / 列出 / 停止 sub-agent 任务（持久化版的 TODO）。
 *
 * 跟 TodoWrite 区别：
 * - TodoWrite：LLM 工作记忆里的轻量 checklist，不入库；适合一次对话内的多步追踪
 * - Task*：持久化任务（agent_task_tracker 表），跨 session 可见；适合派 sub-agent 干长活
 *
 * 4 个工具（对齐 CC Task* 6 个的核心子集，TaskGet / TaskOutput 暂跳）：
 *   TaskCreate / TaskUpdate / TaskList / TaskStop
 */

import { Injectable, BadRequestException } from '@nestjs/common';
import { TaskTrackerService } from '../subagent/task-tracker.service';
import type { AgentTaskStatus } from '@prisma/client';
import type { AgentTool, ToolDescriptor, ToolInvocation, ToolResult } from './tool.types';

@Injectable()
export class TaskCreateTool implements AgentTool {
  constructor(private readonly tracker: TaskTrackerService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'TaskCreate',
    description:
      '创建一个**持久化任务**（agent_task_tracker 一行），跨 session 可见。' +
      '适合派 sub-agent 干长活 / 跟踪用户工单。' +
      '区别 TodoWrite：那是 LLM 工作记忆 checklist；TaskCreate 是真任务存库。',
    inputSchema: {
      title: { type: 'string', required: true, description: '任务标题（≤ 255 字符）' },
      description: { type: 'string', description: '任务详情（可选，markdown 友好）' },
      parentTaskId: { type: 'string', description: '父任务 id（树形结构；可选）' },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: true,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const title = String(inv.input.title ?? '').trim();
    if (!title) return { ok: false, errorMessage: 'title 不能为空' };
    if (title.length > 255) return { ok: false, errorMessage: 'title 过长（max 255）' };
    if (!inv.sessionId) return { ok: false, errorMessage: '需要 sessionId（在 session 内调用）' };
    const task = await this.tracker.create({
      organizationId: inv.organizationId,
      sessionId: inv.sessionId,
      title,
      description: String(inv.input.description ?? '') || undefined,
      parentTaskId: String(inv.input.parentTaskId ?? '') || undefined,
      createdById: inv.userId,
    });
    return { ok: true, output: { task } };
  }
}

@Injectable()
export class TaskUpdateTool implements AgentTool {
  constructor(private readonly tracker: TaskTrackerService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'TaskUpdate',
    description:
      '更新任务状态 / 进度。status 可选 PENDING / IN_PROGRESS / COMPLETED / CANCELLED / FAILED。',
    inputSchema: {
      taskId: { type: 'string', required: true, description: '任务 id' },
      status: { type: 'string', description: 'PENDING/IN_PROGRESS/COMPLETED/CANCELLED/FAILED' },
      progress: { type: 'number', description: '0-100 整数' },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: true,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const taskId = String(inv.input.taskId ?? '').trim();
    if (!taskId) return { ok: false, errorMessage: 'taskId 不能为空' };
    const status = inv.input.status as AgentTaskStatus | undefined;
    if (status && !['PENDING', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED', 'FAILED'].includes(String(status))) {
      throw new BadRequestException(`invalid status: ${status}`);
    }
    const progress = typeof inv.input.progress === 'number' ? Math.max(0, Math.min(100, Math.round(inv.input.progress))) : undefined;
    const task = await this.tracker.updateStatus(taskId, inv.organizationId, { status, progress });
    return { ok: true, output: { task } };
  }
}

@Injectable()
export class TaskListTool implements AgentTool {
  constructor(private readonly tracker: TaskTrackerService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'TaskList',
    description: '列出当前 session 的所有任务（含状态 / 进度）。',
    inputSchema: {},
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: false,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    if (!inv.sessionId) return { ok: false, errorMessage: '需要 sessionId' };
    const tasks = await this.tracker.listForSession(inv.sessionId, inv.organizationId);
    return { ok: true, output: { tasks, total: tasks.length } };
  }
}

@Injectable()
export class TaskStopTool implements AgentTool {
  constructor(private readonly tracker: TaskTrackerService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'TaskStop',
    description: '取消任务（设为 CANCELLED）。',
    inputSchema: {
      taskId: { type: 'string', required: true, description: '任务 id' },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: true,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const taskId = String(inv.input.taskId ?? '').trim();
    if (!taskId) return { ok: false, errorMessage: 'taskId 不能为空' };
    const task = await this.tracker.updateStatus(taskId, inv.organizationId, { status: 'CANCELLED' });
    return { ok: true, output: { task } };
  }
}
