/**
 * 内置工具：后台任务执行器 + 状态查询
 *
 * __bg_exec__: AI 调用 Bash(__bg_exec__ '<json>') 提交后台任务
 * __bg_status__: AI 调用 Bash(__bg_status__) 或 Bash(__bg_status__ '<taskId>') 查询任务状态
 *
 * 飞书端不支持此工具（无法自动发起新 query 投递结果）。
 */

import { backgroundTaskPool } from './background-task-pool.js';
import { evaluate as evaluateToolGuard } from '../tool-guard/index.js';

const ENABLED = process.env.BG_TASK_ENABLED !== 'false';

// ─── __bg_exec__：提交后台任务 ───

export default {
  name: '__bg_exec__',

  // 不需要 responseType — 结果通过 PendingResultQueue 投递，不走 resolveResponse 路径

  systemPrompt: `

## 后台任务执行器

当你需要执行可能耗时超过 30 秒的命令时（如 git clone、npm install、大型构建、长时间脚本等），
使用后台任务执行器代替 Bash 的 run_in_background + TaskOutput 轮询模式。

### 提交后台任务
\`\`\`bash
__bg_exec__ '{"command":"要执行的命令","timeout":600000,"label":"任务描述"}'
\`\`\`
参数说明：
- command（必需）：要执行的 shell 命令
- timeout（可选）：超时时间（毫秒），默认 600000（10分钟），最大 1800000（30分钟）
- label（可选）：人类可读的任务描述

任务会在后台执行，你会立即收到任务 ID 确认。任务完成后结果会自动推送给你，
你不需要轮询或等待，可以继续处理其他工作。

### 查询任务状态
\`\`\`bash
__bg_status__
\`\`\`
不带参数：列出当前会话所有后台任务的状态。

\`\`\`bash
__bg_status__ bg_xxxxxxxxxxxx
\`\`\`
带任务 ID：查询指定任务的详细状态（包含已产生的输出）。

注意事项：
- 每个用户最多同时运行 3 个后台任务
- 不要对交互式命令使用此工具（如需要用户输入的命令）
- 不要对很快就能完成的命令使用此工具（<30 秒的用普通 Bash）
- 如果服务器重启，正在运行的后台任务会丢失
- 不要使用 TaskOutput 来查询后台任务状态，请使用 __bg_status__
`,

  match(hookInput) {
    if (!ENABLED) return false;
    return hookInput.tool_name === 'Bash' &&
      hookInput.tool_input?.command?.trimStart().startsWith('__bg_exec__');
  },

  async execute(hookInput, context) {
    const { userUuid, mutableWriter, cwd } = context;

    // 飞书模式检测
    if (!mutableWriter?.current?.ws) {
      return { decision: 'deny', reason: '后台任务执行功能仅支持网页端使用。' };
    }

    // 解析参数
    const rawArgs = hookInput.tool_input.command.replace(/^\s*__bg_exec__\s*/, '');
    let jsonStr = rawArgs.trim().replace(/^[\u2018\u201C'"]|[\u2019\u201D'"]+$/g, '').trim();

    let params;
    try {
      params = JSON.parse(jsonStr);
    } catch (e) {
      return { decision: 'deny', reason: `参数解析失败: ${e.message}。请使用 JSON 格式：__bg_exec__ '{"command":"..."}'` };
    }

    if (!params.command || typeof params.command !== 'string') {
      return { decision: 'deny', reason: '缺少必需参数 command（要执行的命令）。' };
    }

    const actualCommand = params.command.trim();
    if (!actualCommand) {
      return { decision: 'deny', reason: 'command 不能为空。' };
    }

    // ToolGuard 安全检查（对实际命令而非 __bg_exec__ 包装）
    try {
      const guardResult = await evaluateToolGuard('Bash', { command: actualCommand }, {
        userUuid,
        cwd,
      });
      if (!guardResult.allowed) {
        return { decision: 'deny', reason: `[系统安全策略] ${guardResult.reason}` };
      }
    } catch (err) {
      console.error(`[BgTask] ToolGuard error:`, err.message);
      // 守卫出错不阻塞，降级为允许
    }

    // 提交到进程池
    let task;
    try {
      task = backgroundTaskPool.submit({
        userUuid,
        sessionId: mutableWriter.getSessionId(),
        cwd,
        command: actualCommand,
        timeout: params.timeout,
        label: params.label,
      });
    } catch (err) {
      return { decision: 'deny', reason: `后台任务提交失败: ${err.message}` };
    }

    // sessionId 可能在新会话的第一个 turn 内尚未建立（getSessionId() 返回 null）。
    // 轮询直到 session-created 事件触发后 mutableWriter 持有真实 sessionId，
    // 避免任务完成时以 null sessionId 投递导致前端无法匹配。
    if (!task.sessionId) {
      const pollTimer = setInterval(() => {
        const sid = mutableWriter.getSessionId();
        if (sid) {
          task.sessionId = sid;
          clearInterval(pollTimer);
        }
      }, 200);
      // 最多等 60 秒，之后放弃（任务完成时 sessionId 仍为 null 则依赖前端兜底匹配）
      setTimeout(() => clearInterval(pollTimer), 60_000);
    }

    const timeoutSec = Math.round(task.timeout / 1000);
    return {
      decision: 'deny',
      reason: `后台任务已启动。\n` +
        `- 任务 ID: ${task.id}\n` +
        `- 命令: ${actualCommand}\n` +
        `- 超时: ${timeoutSec}s\n` +
        `任务完成后结果会自动推送给你，请继续处理其他工作。`,
    };
  }
};

// ─── __bg_status__：查询后台任务状态 ───

function formatDuration(ms) {
  if (ms < 1000) return `${ms}ms`;
  const s = Math.round(ms / 1000);
  if (s < 60) return `${s}s`;
  return `${Math.floor(s / 60)}m${s % 60}s`;
}

function formatTaskSummary(task) {
  const elapsed = (task.endTime || Date.now()) - task.startTime;
  const lines = [
    `[${task.id}] ${task.status.toUpperCase()}`,
    `  命令: ${task.command}`,
    `  耗时: ${formatDuration(elapsed)}`,
  ];
  if (task.status !== 'running') {
    lines.push(`  退出码: ${task.exitCode ?? 'N/A'}`);
  }
  if (task.label && task.label !== task.command.slice(0, 80)) {
    lines.splice(1, 0, `  标签: ${task.label}`);
  }
  return lines.join('\n');
}

function formatTaskDetail(task) {
  const elapsed = (task.endTime || Date.now()) - task.startTime;
  const lines = [
    `任务 ID: ${task.id}`,
    `状态: ${task.status}`,
    `命令: ${task.command}`,
    `耗时: ${formatDuration(elapsed)}`,
    `退出码: ${task.exitCode ?? 'N/A'}`,
  ];
  if (task.truncated) lines.push('(输出已截断至 100KB)');
  if (task.stdout) lines.push('', '--- STDOUT ---', task.stdout);
  if (task.stderr) lines.push('', '--- STDERR ---', task.stderr);
  if (task.status === 'running' && !task.stdout && !task.stderr) {
    lines.push('', '(暂无输出)');
  }
  return lines.join('\n');
}

export const bgStatusTool = {
  name: '__bg_status__',

  // systemPrompt 合并在 __bg_exec__ 的 systemPrompt 中，不需要单独的

  systemPrompt: '',

  match(hookInput) {
    if (!ENABLED) return false;
    return hookInput.tool_name === 'Bash' &&
      hookInput.tool_input?.command?.trimStart().startsWith('__bg_status__');
  },

  async execute(hookInput, context) {
    const { userUuid, mutableWriter } = context;
    const sessionId = mutableWriter?.getSessionId();

    // 解析可选的 taskId 参数
    const rawArgs = hookInput.tool_input.command.replace(/^\s*__bg_status__\s*/, '').trim();
    // 去掉可能的引号
    let taskId = rawArgs.replace(/^['"]|['"]$/g, '').trim();

    if (taskId) {
      // 查询指定任务
      const task = backgroundTaskPool.getTask(taskId);
      if (!task) {
        return { decision: 'deny', reason: `未找到任务 ${taskId}。任务可能已过期被清理。` };
      }
      if (task.userUuid !== userUuid) {
        return { decision: 'deny', reason: `未找到任务 ${taskId}。` };
      }
      return { decision: 'deny', reason: formatTaskDetail(task) };
    }

    // 列出当前会话所有任务
    const tasks = sessionId
      ? backgroundTaskPool.getSessionTasks(userUuid, sessionId)
      : backgroundTaskPool.getUserTasks(userUuid);

    if (tasks.length === 0) {
      return { decision: 'deny', reason: '当前没有后台任务。' };
    }

    const lines = [`后台任务列表（共 ${tasks.length} 个）：`, ''];
    for (const task of tasks) {
      lines.push(formatTaskSummary(task), '');
    }
    return { decision: 'deny', reason: lines.join('\n') };
  }
};
