#!/usr/bin/env node
'use strict';

/**
 * easyagent 批处理模式
 * 用于子智能体执行，不需要交互式 CLI
 */

const fs = require('fs');
const path = require('path');
const { streamChat } = require('../model/client');
const { executeTool } = require('../tools/dispatcher');
const { getModelByKey } = require('../config');
const { applyUsage, normalizeUsagePayload } = require('../utils/token_usage');

// 解析命令行参数
function parseArgs() {
  const args = process.argv.slice(2);
  const config = {
    workspace: process.cwd(),
    taskFile: null,
    systemPromptFile: null,
    outputFile: null,
    statsFile: null,
    progressFile: null,
    agentId: null,
    modelKey: null,
    thinkingMode: null,
    timeout: 600,
  };

  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    if (arg === '--workspace' && i + 1 < args.length) {
      config.workspace = args[++i];
    } else if (arg === '--task-file' && i + 1 < args.length) {
      config.taskFile = args[++i];
    } else if (arg === '--system-prompt-file' && i + 1 < args.length) {
      config.systemPromptFile = args[++i];
    } else if (arg === '--output-file' && i + 1 < args.length) {
      config.outputFile = args[++i];
    } else if (arg === '--stats-file' && i + 1 < args.length) {
      config.statsFile = args[++i];
    } else if (arg === '--progress-file' && i + 1 < args.length) {
      config.progressFile = args[++i];
    } else if (arg === '--agent-id' && i + 1 < args.length) {
      config.agentId = args[++i];
    } else if (arg === '--model-key' && i + 1 < args.length) {
      config.modelKey = args[++i];
    } else if (arg === '--thinking-mode' && i + 1 < args.length) {
      config.thinkingMode = String(args[++i] || '').trim().toLowerCase();
    } else if (arg === '--timeout' && i + 1 < args.length) {
      config.timeout = parseInt(args[++i], 10);
    }
  }

  return config;
}

// 读取文件内容
function readFile(filePath) {
  try {
    return fs.readFileSync(filePath, 'utf8');
  } catch (err) {
    console.error(`读取文件失败: ${filePath}`, err);
    process.exit(1);
  }
}

// 写入输出文件
function writeOutput(filePath, data) {
  try {
    fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
  } catch (err) {
    console.error(`写入输出文件失败: ${filePath}`, err);
  }
}

// 更新统计文件
function updateStats(statsFile, stats) {
  try {
    fs.writeFileSync(statsFile, JSON.stringify(stats, null, 2), 'utf8');
  } catch (err) {
    console.error(`更新统计文件失败: ${statsFile}`, err);
  }
}

function appendProgress(progressFile, entry) {
  if (!progressFile) return;
  try {
    const dir = path.dirname(progressFile);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    fs.appendFileSync(progressFile, `${JSON.stringify(entry)}\n`, 'utf8');
  } catch (err) {
    console.error(`写入进度失败: ${progressFile}`, err);
  }
}

// 主函数
async function main() {
  const config = parseArgs();

  if (!config.taskFile || !config.systemPromptFile || !config.outputFile) {
    console.error('缺少必需参数: --task-file, --system-prompt-file, --output-file');
    process.exit(1);
  }

  // 读取任务和系统提示
  const taskMessage = readFile(config.taskFile);
  const systemPrompt = readFile(config.systemPromptFile);

  // 加载模型配置
  const modelConfig = require('../config');
  const ensuredConfig = modelConfig.ensureConfig();

  if (!ensuredConfig.valid_models || ensuredConfig.valid_models.length === 0) {
    writeOutput(config.outputFile, {
      success: false,
      summary: '未找到可用模型配置',
      error: 'no_model_config',
    });
    process.exit(1);
  }

  // 使用指定模型或默认模型
  const modelKey = config.modelKey || ensuredConfig.default_model_key;
  const model = getModelByKey(ensuredConfig, modelKey);

  if (!model) {
    writeOutput(config.outputFile, {
      success: false,
      summary: `未找到模型: ${modelKey}`,
      error: 'model_not_found',
    });
    process.exit(1);
  }

  // 加载工具定义
  const tools = JSON.parse(fs.readFileSync(path.join(__dirname, '../../doc/tools.json'), 'utf8'));

  // 添加 finish_task 工具
  tools.push({
    type: 'function',
    function: {
      name: 'finish_task',
      description: '完成当前任务并退出。调用此工具表示你已经完成了分配的任务，所有交付文件已准备好。',
      parameters: {
        type: 'object',
        properties: {
          success: {
            type: 'boolean',
            description: '任务是否成功完成。true=成功完成所有要求；false=部分完成或遇到问题无法继续。',
          },
          summary: {
            type: 'string',
            description: '任务完成摘要（50-200字），说明完成了什么工作、生成了哪些文件、关键发现或结果。如果失败，说明原因和已完成的部分。',
          },
        },
        required: ['success', 'summary'],
      },
    },
  });

  // 初始化对话
  const messages = [
    { role: 'system', content: systemPrompt },
    { role: 'user', content: taskMessage },
  ];

  // 统计信息
  const stats = {
    runtime_start: Date.now(),
    runtime_seconds: 0,
    files_read: 0,
    edit_files: 0,
    searches: 0,
    web_pages: 0,
    commands: 0,
    api_calls: 0,
    token_usage: { prompt: 0, completion: 0, total: 0 },
  };

  const startTime = Date.now();
  const timeoutMs = config.timeout * 1000;
  let turnCount = 0;
  const maxTurns = 50; // 防止无限循环

  try {
    while (true) {
      turnCount++;
      stats.api_calls += 1;
      stats.turn_count = turnCount;

      // 检查超时
      const elapsed = Date.now() - startTime;
      if (elapsed > timeoutMs) {
        writeOutput(config.outputFile, {
          success: false,
          summary: '任务超时未完成',
          timeout: true,
          stats: {
            ...stats,
            runtime_seconds: Math.floor(elapsed / 1000),
          },
        });
        process.exit(1);
      }

      // 检查轮次限制
      if (turnCount > maxTurns) {
        writeOutput(config.outputFile, {
          success: false,
          summary: `任务执行超过 ${maxTurns} 轮，可能陷入循环`,
          max_turns_exceeded: true,
          stats: {
            ...stats,
            runtime_seconds: Math.floor(elapsed / 1000),
          },
        });
        process.exit(1);
      }

      // 更新统计文件
      if (config.statsFile) {
        updateStats(config.statsFile, {
          ...stats,
          runtime_seconds: Math.floor(elapsed / 1000),
          turn_count: turnCount,
        });
      }

      // 调用 API
      let assistantMessage = { role: 'assistant', content: '', tool_calls: [] };
      let reasoningBuffer = '';
      let currentToolCall = null;
      let usage = null;

      try {
        for await (const chunk of streamChat({
          config: ensuredConfig,
          modelKey,
          messages,
          tools,
          thinkingMode: config.thinkingMode === 'thinking',
          currentContextTokens: 0,
          abortSignal: null,
        })) {
          const choice = chunk.choices?.[0];
          const delta = choice?.delta;
          if (!delta) continue;

          // 处理内容
          if (delta.content) {
            assistantMessage.content += delta.content;
          }

          // 处理 reasoning_content（兼容 reasoning_details）
          if (delta.reasoning_content || delta.reasoning_details || choice?.reasoning_details) {
            let rc = '';
            if (delta.reasoning_content) {
              rc = delta.reasoning_content;
            } else if (delta.reasoning_details) {
              if (Array.isArray(delta.reasoning_details)) {
                rc = delta.reasoning_details.map((d) => d.text || '').join('');
              } else if (typeof delta.reasoning_details === 'string') {
                rc = delta.reasoning_details;
              } else if (delta.reasoning_details && typeof delta.reasoning_details.text === 'string') {
                rc = delta.reasoning_details.text;
              }
            } else if (choice?.reasoning_details) {
              if (Array.isArray(choice.reasoning_details)) {
                rc = choice.reasoning_details.map((d) => d.text || '').join('');
              } else if (typeof choice.reasoning_details === 'string') {
                rc = choice.reasoning_details;
              } else if (choice.reasoning_details && typeof choice.reasoning_details.text === 'string') {
                rc = choice.reasoning_details.text;
              }
            }
            if (rc) reasoningBuffer += rc;
          }

          // 处理工具调用
          if (delta.tool_calls) {
            for (const tc of delta.tool_calls) {
              if (tc.index !== undefined) {
                if (!assistantMessage.tool_calls[tc.index]) {
                  assistantMessage.tool_calls[tc.index] = {
                    id: tc.id || '',
                    type: 'function',
                    function: { name: '', arguments: '' },
                  };
                  currentToolCall = assistantMessage.tool_calls[tc.index];
                } else {
                  currentToolCall = assistantMessage.tool_calls[tc.index];
                }

                if (tc.id) currentToolCall.id = tc.id;
                if (tc.function?.name) currentToolCall.function.name += tc.function.name;
                if (tc.function?.arguments) currentToolCall.function.arguments += tc.function.arguments;
              }
            }
          }

          // 处理 usage
          if (chunk.usage) {
            usage = normalizeUsagePayload(chunk.usage);
          }
        }
      } catch (err) {
        writeOutput(config.outputFile, {
          success: false,
          summary: `API 调用失败: ${err.message}`,
          error: 'api_error',
          stats: {
            ...stats,
            runtime_seconds: Math.floor((Date.now() - startTime) / 1000),
          },
        });
        process.exit(1);
      }

      // 更新 token 统计
      if (usage) {
        applyUsage(stats.token_usage, usage);
      }

      // 添加助手消息到历史（reasoning_content 放在 content 前）
      const finalAssistantMessage = reasoningBuffer
        ? {
            role: 'assistant',
            reasoning_content: reasoningBuffer,
            content: assistantMessage.content,
            tool_calls: assistantMessage.tool_calls,
          }
        : assistantMessage;
      messages.push(finalAssistantMessage);

      // 如果没有工具调用，检查是否忘记调用 finish_task
      if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
        // 兜底机制：提醒调用 finish_task
        messages.push({
          role: 'user',
          content: '如果你已经完成了任务，请调用 finish_task 工具提交完成报告。如果还没有完成，请继续执行任务。',
        });
        continue;
      }

      // 执行工具调用
      for (const toolCall of assistantMessage.tool_calls) {
        const toolName = toolCall.function.name;
        stats.tool_calls = (stats.tool_calls || 0) + 1;

        // 检查是否是 finish_task
        if (toolName === 'finish_task') {
          let args = {};
          try {
            args = JSON.parse(toolCall.function.arguments || '{}');
          } catch (err) {
            writeOutput(config.outputFile, {
              success: false,
              summary: 'finish_task 参数解析失败',
              error: 'invalid_finish_args',
              stats: {
                ...stats,
                runtime_seconds: Math.floor((Date.now() - startTime) / 1000),
              },
            });
            process.exit(1);
          }

          // 保存对话记录到交付目录的 .subagent/ 子目录
          try {
            // 从任务文件路径推断交付目录
            const taskFileDir = path.dirname(config.taskFile);
            // 读取任务消息以获取交付目录路径
            const taskContent = fs.readFileSync(config.taskFile, 'utf8');
            const deliverablesDirMatch = taskContent.match(/\*\*交付目录\*\*：(.+)/);
            if (deliverablesDirMatch) {
              const deliverablesDirPath = deliverablesDirMatch[1].split('\n')[0].trim();
              const subagentDir = path.join(deliverablesDirPath, '.subagent');

              // 确保目录存在
              if (!fs.existsSync(subagentDir)) {
                fs.mkdirSync(subagentDir, { recursive: true });
              }

              // 保存对话记录
              const conversationData = {
                agent_id: config.agentId,
                created_at: new Date(startTime).toISOString(),
                completed_at: new Date().toISOString(),
                success: args.success,
                summary: args.summary,
                messages: messages,
                stats: {
                  ...stats,
                  runtime_seconds: Math.floor((Date.now() - startTime) / 1000),
                },
              };

              const conversationFile = path.join(subagentDir, 'conversation.json');
              fs.writeFileSync(conversationFile, JSON.stringify(conversationData, null, 2), 'utf8');
            }
          } catch (err) {
            // 保存对话记录失败不影响任务完成
            console.error('保存对话记录失败:', err);
          }

          // 写入输出并退出
          writeOutput(config.outputFile, {
            success: args.success || false,
            summary: args.summary || '任务完成',
            stats: {
              ...stats,
              runtime_seconds: Math.floor((Date.now() - startTime) / 1000),
            },
          });
          process.exit(0);
        }

        let progressArgs = {};
        try {
          progressArgs = JSON.parse(toolCall.function.arguments || '{}');
        } catch (err) {
          progressArgs = { _raw: toolCall.function.arguments || '' };
        }
        const progressId = toolCall.id || `tool_${Date.now()}_${Math.random().toString(16).slice(2, 8)}`;
        appendProgress(config.progressFile, {
          id: progressId,
          tool: toolName,
          status: 'running',
          args: progressArgs,
          ts: Date.now(),
        });

        // 执行其他工具
        const result = await executeTool({
          workspace: config.workspace,
          config: ensuredConfig,
          allowMode: 'full_access',
          toolCall,
          abortSignal: null,
        });

        appendProgress(config.progressFile, {
          id: progressId,
          tool: toolName,
          status: result && result.success ? 'completed' : 'failed',
          args: progressArgs,
          ts: Date.now(),
        });

        // 更新统计
        if (toolName === 'read_file') stats.files_read++;
        else if (toolName === 'edit_file') stats.edit_files++;
        else if (toolName === 'search_workspace') stats.searches++;
        else if (toolName === 'web_search' || toolName === 'extract_webpage') stats.web_pages++;
        else if (toolName === 'run_command') stats.commands++;

        // 添加工具结果到历史
        messages.push({
          role: 'tool',
          tool_call_id: toolCall.id,
          content: result.formatted || '',
        });
      }
    }
  } catch (err) {
    writeOutput(config.outputFile, {
      success: false,
      summary: `执行出错: ${err.message}`,
      error: 'execution_error',
      stats: {
        ...stats,
        runtime_seconds: Math.floor((Date.now() - startTime) / 1000),
      },
    });
    process.exit(1);
  }
}

// 运行
main().catch((err) => {
  console.error('批处理模式执行失败:', err);
  process.exit(1);
});
