/**
 * weixin_send_text 工具 — 在指定微信群发送一段文字。
 *
 * 设计要点：
 *  1. 通过工厂函数注入依赖（DesktopOpService + channelRepo），与其他 builtin 保持一致。
 *  2. channelId 优先从 bizContext 取，其次从显式参数取。
 *  3. 校验 channel.config.weixinReply.enabled === true，否则拒绝执行。
 *  4. 根据 watermark 配置对文本加水印（suffix / zero-width / none）。
 *  5. 组装 DesktopTask 调用 runAndWait，同步等待最多 60s。
 *  6. 成功返回 textResult；失败直接 throw，让上层 Agent 看到原始错误。
 */

import { Type } from '@sinclair/typebox';
import { AgentToolWithMeta, textResult } from '../common.js';
import { registerSchema, TOOLSET_WEIXIN_DESKTOP } from '../catalog.js';
import { readToolRuntimeContext } from '../runtime_context.js';
import { randomUUID } from 'node:crypto';

/** 工具参数 Schema */
const Params = Type.Object({
  /** 目标群名，必填 */
  roomName: Type.String({ description: '目标群名,必填' }),
  /** 要发送的文本，1-2000 字符 */
  text: Type.String({ description: '要发送的文本,1-2000 字符' }),
  /** NetaClaw channel id，可不传，优先从 bizContext 取 */
  channelId: Type.Optional(Type.Number({
    description: 'NetaClaw channel id,可不传,优先从 bizContext 取',
  })),
  /** 运行时上下文，由框架注入 */
  _netaRuntime: Type.Optional(Type.Any()),
});

/** createWeixinSendTextTool 所需的外部依赖 */
export interface WeixinSendTextDeps {
  /** Desktop Op 服务，提供 runAndWait 执行桌面任务 */
  desktopOpService: {
    runAndWait(task: any, timeoutMs?: number): Promise<{
      ok: true;
      taskId: string;
      modelCalls: number;
      steps: number;
      durationMs: number;
    }>;
  };
  /** Agent Channel 仓库，用于查询频道配置 */
  channelRepo: {
    findOne(opts: any): Promise<any>;
  };
}

/**
 * 创建 weixin_send_text 工具实例。
 *
 * @param deps 注入的外部依赖
 */
export function createWeixinSendTextTool(
  deps: WeixinSendTextDeps,
): AgentToolWithMeta<typeof Params, unknown> {
  return {
    name: 'weixin_send_text',
    label: '微信发送文字',
    description: '在指定微信群里发送一段文字',
    parameters: Params,
    async execute(_id, params) {
      // 读取运行时上下文，获取 channelId 和 modelChannelId
      const runtime = readToolRuntimeContext(params as any);
      // v4 临时诊断
      // eslint-disable-next-line no-console
      console.log('[weixin_send_text DEBUG] runtime=%j params.channelId=%s', runtime, params.channelId);
      // bizContext 中的 channelId 优先于显式参数
      const channelId = runtime?.bizContext?.channelId ?? params.channelId;
      const modelChannelId = runtime?.currentAgent?.modelChannelId;

      // 参数校验：channelId 必须存在
      if (!channelId) {
        throw new Error('invalid-params: channelId 缺失(既无 bizContext 也无显式参数)');
      }
      // 参数校验：desktop agent 必须配置 modelChannel
      if (!modelChannelId) {
        throw new Error('current-agent-model-channel-missing: desktop agent 未配置 modelChannel');
      }
      // 参数校验：文本不能为空
      if (!params.text || params.text.length === 0) {
        throw new Error('text-empty');
      }
      // 参数校验：文本不能超过 2000 字符
      if (params.text.length > 2000) {
        throw new Error('text-too-long');
      }
      const roomName = params.roomName?.trim() || runtime?.bizContext?.roomName?.trim();
      // 参数校验：群名不能为空
      if (!roomName) {
        throw new Error('invalid-params: roomName 缺失');
      }

      // 查询频道配置
      const channel = await deps.channelRepo.findOne({ where: { id: channelId } });
      if (!channel) {
        throw new Error('channel-not-found: ' + channelId);
      }

      // 校验 weixinReply 是否已启用
      const cfg = (channel.config as any)?.weixinReply;
      if (!cfg?.enabled) {
        throw new Error('weixin-reply-not-enabled');
      }

      // 根据 watermark 配置加水印
      const watermark = cfg.watermark ?? 'suffix';
      let finalText = params.text;
      if (watermark === 'suffix') {
        // 后缀水印：追加 " —AI"
        finalText = params.text + ' —AI';
      } else if (watermark === 'zero-width') {
        // 零宽水印：在开头插入 U+200B（零宽空格）
        finalText = '​' + params.text;
      }
      // watermark === 'none' 时不做任何修改

      // 组装 DesktopTask
      const task = {
        id: `cid-${channelId}-${randomUUID()}`,
        appId: 'weixin',
        target: { conversation: roomName, channelId, roomName },
        actionType: 'send-text',
        params: { text: finalText, originalText: params.text },
        modelChannelId,
        maxSteps: 8,
        enqueuedAt: Date.now(),
      };

      // 调用 runAndWait，同步等待最多 60 秒
      const result = await deps.desktopOpService.runAndWait(task, 60000);

      // 构造预览文本（超过 60 字符截断）
      const preview = params.text.slice(0, 60);
      const ellipsis = params.text.length > 60 ? '...' : '';

      return textResult(
        `已在群 "${roomName}" 发送: ${preview}${ellipsis} (taskId=${result.taskId}, ${result.durationMs}ms)`,
      );
    },
  };
}

// 在工具目录中注册 Schema 元数据
registerSchema({
  name: 'weixin_send_text',
  toolset: TOOLSET_WEIXIN_DESKTOP,
  description: '在指定微信群里发送一段文字',
  visibility: 'tool',
  capability: 'text',
  isCore: false,
  canDisable: true,
});
