/**
 * Cron* 工具集 —— LLM 帮用户创建 / 查 / 改 / 删定时任务。
 *
 * 4 个工具（对齐 CC CronCreate / CronList / CronUpdate / CronDelete）：
 * - CronCreate：创建定时任务（cron 表达式 + prompt + sessionId）
 * - CronList：列出当前用户的 cron
 * - CronUpdate：改 cronExpr / prompt / enabled
 * - CronDelete：删
 *
 * 用法示例：用户说"每天早上 9 点给我发昨天的销售数字"
 *   → LLM 调 CronCreate({ name: "每日销售", cronExpr: "0 9 * * *",
 *                          prompt: "总结昨天销售数字", sessionId: <当前 session>})
 *   → 后续每天 9 点心跳触发 → 走完整 LLM pipeline → 结果落到指定 session
 */

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

@Injectable()
export class CronCreateTool implements AgentTool {
  constructor(private readonly crons: AgentCronsService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'CronCreate',
    description:
      '创建定时任务（5 字段 cron 表达式 + prompt）。触发时把 prompt 当 user message 走 LLM pipeline，结果落到 sessionId 指定的会话。' +
      '用例："每天 9 点发昨天销售" → cronExpr="0 9 * * *" prompt="..." sessionId=<当前 session>。' +
      'cron 字段顺序：分 时 日 月 周（POSIX；UTC 时区）。' +
      '常见：每分钟 "* * * * *"，每天 9 点 "0 9 * * *"，每工作日 9 点 "0 9 * * 1-5"，每周一 8 点 "0 8 * * 1"。',
    inputSchema: {
      name: { type: 'string', required: true, description: '任务名（≤ 120 字符）' },
      cronExpr: { type: 'string', required: true, description: 'POSIX cron 表达式，UTC 时区' },
      prompt: { type: 'string', required: true, description: '触发时喂给 LLM 的 prompt（≤ 4000 字符）' },
      sessionId: { type: 'string', description: '结果落到的会话 id（不传走当前 sessionId）' },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: true,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const sessionId = String(inv.input.sessionId ?? inv.sessionId ?? '').trim();
    if (!sessionId) return { ok: false, errorMessage: 'sessionId 不能为空（建议传当前 session）' };
    const cron = await this.crons.create({
      organizationId: inv.organizationId,
      createdById: inv.userId,
      sessionId,
      name: String(inv.input.name ?? ''),
      cronExpr: String(inv.input.cronExpr ?? ''),
      prompt: String(inv.input.prompt ?? ''),
    });
    return { ok: true, output: { cron } };
  }
}

@Injectable()
export class CronListTool implements AgentTool {
  constructor(private readonly crons: AgentCronsService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'CronList',
    description: '列出当前用户的所有定时任务（含 enabled / nextRunAt / lastRunAt / runCount）。',
    inputSchema: {},
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: false,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const crons = await this.crons.list(inv.organizationId, inv.userId);
    return { ok: true, output: { crons, total: crons.length } };
  }
}

@Injectable()
export class CronUpdateTool implements AgentTool {
  constructor(private readonly crons: AgentCronsService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'CronUpdate',
    description: '更新定时任务：可改 name / cronExpr / prompt / enabled。',
    inputSchema: {
      cronId: { type: 'string', required: true, description: '定时任务 id' },
      name: { type: 'string', description: '新名字' },
      cronExpr: { type: 'string', description: '新 cron 表达式' },
      prompt: { type: 'string', description: '新 prompt' },
      enabled: { type: 'boolean', description: '启用 / 停用' },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: true,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const id = String(inv.input.cronId ?? '').trim();
    if (!id) return { ok: false, errorMessage: 'cronId 不能为空' };
    const cron = await this.crons.update(id, inv.organizationId, inv.userId, {
      name: inv.input.name as string | undefined,
      cronExpr: inv.input.cronExpr as string | undefined,
      prompt: inv.input.prompt as string | undefined,
      enabled: inv.input.enabled as boolean | undefined,
    });
    return { ok: true, output: { cron } };
  }
}

@Injectable()
export class CronDeleteTool implements AgentTool {
  constructor(private readonly crons: AgentCronsService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'CronDelete',
    description: '删除定时任务。',
    inputSchema: {
      cronId: { type: 'string', required: true, description: '定时任务 id' },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams', 'cli'] },
    writeAction: true,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const id = String(inv.input.cronId ?? '').trim();
    if (!id) return { ok: false, errorMessage: 'cronId 不能为空' };
    return { ok: true, output: await this.crons.remove(id, inv.organizationId, inv.userId) };
  }
}
