import { Injectable } from '@nestjs/common';
import { randomUUID } from 'crypto';
import { ApprovalService } from '@engines/approval/approval.service';
import type { AgentTool, ToolDescriptor, ToolInvocation, ToolResult } from './tool.types';

/**
 * `approval_submit` tool —— PR6 真后端接入。
 *
 * 走 Approval engine `ApprovalService.startApproval(dto, initiatorId)` —— 真启动审批流。
 *
 * **写动作**：descriptor.writeAction=true → Plan / READ_ONLY mode 下被 ToolRegistry 屏蔽（PR4.5）
 */
@Injectable()
export class ApprovalSubmitTool implements AgentTool {
  constructor(private readonly approvalService: ApprovalService) {}

  readonly descriptor: ToolDescriptor = {
    name: 'approval_submit',
    description:
      '启动一个审批流程（如出差/报销/采购）—— 真实接入 Approval Engine。' +
      ' 必须提供 processDefinitionKey（流程定义 KEY）+ businessType + title；' +
      ' 流程变量通过 variables 传入。',
    inputSchema: {
      processDefinitionKey: {
        type: 'string',
        required: true,
        description: '流程定义编码：BUSINESS_TRIP / EXPENSE / PURCHASE 等',
      },
      businessType: {
        type: 'string',
        required: true,
        description: '业务类型（通常等于 processDefinitionKey 的归类）',
      },
      title: { type: 'string', required: true, description: '审批单标题' },
      variables: {
        type: 'string',
        required: false,
        description: 'JSON 字符串：流程变量（含金额、出差城市、报销项等业务字段）',
      },
    },
    availability: {
      surface: ['web', 'desktop', 'mobile', 'teams'],
      permissions: ['approval:create'],
    },
    writeAction: true,
  };

  async invoke(inv: ToolInvocation): Promise<ToolResult> {
    const processDefinitionKey = String(inv.input.processDefinitionKey ?? '').trim();
    const businessType = String(inv.input.businessType ?? processDefinitionKey).trim();
    const title = String(inv.input.title ?? '').trim();
    if (!processDefinitionKey || !title) {
      return { ok: false, errorMessage: 'processDefinitionKey 和 title 必填' };
    }
    let variables: Record<string, unknown> | undefined;
    if (inv.input.variables) {
      try {
        variables =
          typeof inv.input.variables === 'string'
            ? JSON.parse(inv.input.variables)
            : (inv.input.variables as Record<string, unknown>);
      } catch (err) {
        return { ok: false, errorMessage: `variables JSON 解析失败：${(err as Error).message}` };
      }
    }

    try {
      const response = await this.approvalService.startApproval(
        {
          processDefinitionKey,
          businessType,
          businessId: randomUUID(), // 由 agent 调起的审批用临时 businessId；真实业务侧应传单据 id
          title,
          variables,
        } as any,
        inv.userId,
      );
      return { ok: true, output: response };
    } catch (err) {
      return {
        ok: false,
        errorMessage: `审批启动失败：${(err as Error).message}（可能是 processDefinitionKey 不存在或权限不足）`,
      };
    }
  }
}
