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

/**
 * PR4.5 follow-up: `ask_user` tool —— 让 LLM 在歧义时反问用户而不是猜测。
 *
 * 工作流：
 *   1. LLM 判断 prompt 模糊（如"帮我开个会"没说时间），调 ask_user
 *      input: { question: '会议时间？', options: ['今天下午','明天上午','其他'] }
 *   2. Tool 返回 `{ok:true, output:{pendingQuestion}}`，pendingQuestion 字段是约定的"halt + prompt user"信号
 *   3. messages.service 检测到 pendingQuestion，runTurn/runTurnStream graceful break TAOR loop
 *      并通过 SSE `ask_user` 事件传给前端
 *   4. 前端弹出选项 → 用户点击 → 自动发新 prompt "我选：<option>"
 *
 * 这是 ASK_EVERY_TIME mode 的"降级 fallback"：当前不强制把 writeAction tool 卡死，
 * 而是允许 LLM 调 ask_user 主动问。后续 PR4.5 GA 时再把 writeAction 自动包装成 ask_user。
 */
@Injectable()
export class AskUserTool implements AgentTool {
  readonly descriptor: ToolDescriptor = {
    name: 'ask_user',
    description:
      '需求模糊时反问用户做选择，而不是凭空猜。返回结构化 pendingQuestion，' +
      '父对话会暂停 TAOR loop 等用户回答。最多 5 个 options。',
    inputSchema: {
      question: { type: 'string', required: true, description: '要问用户的问题（5-200 字）' },
      options: {
        type: 'string',
        required: false,
        description: 'JSON 数组字符串，例：["今天下午","明天上午","其他"]。最多 5 项；省略表示开放式回答',
      },
    },
    availability: { surface: ['web', 'desktop', 'mobile', 'teams'] },
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const question = String(inv.input.question ?? '').trim();
    if (!question) return { ok: false, errorMessage: 'question 必填' };
    let options: string[] | undefined;
    const raw = inv.input.options;
    if (raw !== undefined && raw !== '') {
      try {
        const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
        if (Array.isArray(parsed)) {
          options = parsed.slice(0, 5).map((s) => String(s));
        }
      } catch {
        // 解析失败按开放式问题处理
      }
    }
    return {
      ok: true,
      output: { pendingQuestion: { question, options } },
    };
  }
}
