import { Provide, Inject, Controller, Post, Body } from '@midwayjs/core';
import { NetaClawAgentChannelGroupService } from '../../service/agent_channel_group.js';
import { NetaClawAgentChannelService } from '../../service/agent_channel.js';
import { WeixinDbService } from '../../service/weixin_db.js';

const ERROR_MESSAGES: Record<string, string> = {
  'group-not-found': '群记录不存在',
  'channel-not-found': '频道记录不存在',
  'unsupported-channel-type': '本频道不支持同步',
  'channel-not-connected': '频道未连接,请检查 PC 微信是否登录',
  'channel-not-bound': '频道未连接,请检查 PC 微信是否登录',
  'room-not-found': '未找到该群消息,请检查群名是否与 PC 微信中显示的完全一致',
  'decrypt-failed': '解密失败,可能登录态已失效,请重启 PC 微信后重试',
  'unsupported-platform': '本功能需要 Windows + PC 微信',
};

@Provide()
@Controller('/admin/netaclaw/agent_channel_group')
export class NetaClawAgentChannelGroupAdminController {
  @Inject()
  groupService: NetaClawAgentChannelGroupService;

  @Inject()
  channelService: NetaClawAgentChannelService;

  @Inject()
  weixinDbService: WeixinDbService;

  @Post('/list')
  async list(@Body() body: { channelId: number }) {
    if (!body?.channelId) return { code: 1003, message: 'channelId is required' };
    return { code: 1000, data: await this.groupService.list(body.channelId) };
  }

  @Post('/toggle')
  async toggle(@Body() body: { id: number; status: 0 | 1 }) {
    if (!body?.id) return { code: 1003, message: 'id is required' };
    if (body.status !== 0 && body.status !== 1) {
      return { code: 1003, message: 'status must be 0 or 1' };
    }
    try {
      await this.channelService.toggleGroupAndNotify(body.id, body.status);
    } catch (err: any) {
      return { code: 1003, message: err?.message || 'toggle failed' };
    }
    return { code: 1000, message: 'success' };
  }

  @Post('/add')
  async add(@Body() body: {
    channelId: number;
    roomName: string;
    triggerMode?: 'at_mention' | 'all';
    agentId?: number | null;
    replyIdentity?: 'silent' | 'ai_prefix' | null;
  }) {
    if (!body?.channelId || !body?.roomName) {
      return { code: 1003, message: 'channelId + roomName required' };
    }
    const mode: 'at_mention' | 'all' = body.triggerMode === 'all' ? 'all' : 'at_mention';
    try {
      const channel = await this.channelService.info(body.channelId);
      if (channel?.type === 'weixin-db') {
        if (!body.agentId) {
          return { code: 1003, message: 'weixin-db 群聊必须绑定 Agent' };
        }
        if (body.replyIdentity !== 'silent' && body.replyIdentity !== 'ai_prefix') {
          return { code: 1003, message: 'weixin-db 群聊必须选择回复身份' };
        }
      }
      const { id, created } = await this.groupService.addByName(body.channelId, body.roomName, mode, {
        boundAgentId: channel?.type === 'weixin-db' ? body.agentId : null,
        replyIdentityOverride: channel?.type === 'weixin-db' ? body.replyIdentity : null,
      });
      if (created) {
        if (channel?.type === 'weixin-db') {
          await this.weixinDbService.refreshWhitelist(body.channelId);
        }
      }
      return { code: 1000, data: { id, created } };
    } catch (err: any) {
      return { code: 1003, message: err?.message || 'add failed' };
    }
  }

  @Post('/updatePolicy')
  async updatePolicy(@Body() body: { id: number; triggerMode: string; triggerPrefix?: string | null }) {
    if (!body?.id) return { code: 1003, message: 'id is required' };
    if (body.triggerMode === 'at_mention') {
      const entity = await this.groupService.findById(body.id);
      if (entity) {
        const channel = await this.channelService.info(entity.channelId);
        // Task 5: 仅对 weixin (ClawBot) 渠道强校验 botAlias; UIA 渠道直接用账号 nickname 当 alias, 不强制
        if (channel?.type === 'weixin') {
          const alias = (channel?.config as any)?.group?.botAlias;
          if (!alias || !String(alias).trim()) {
            return {
              code: 1003,
              message: '使用 @机器人 触发前，请先在频道编辑页填写 "微信机器人昵称"',
            };
          }
        }
      }
    }
    try {
      await this.groupService.updatePolicy(body.id, body.triggerMode, body.triggerPrefix);
    } catch (err: any) {
      return { code: 1003, message: err?.message || 'updatePolicy failed' };
    }
    return { code: 1000, message: 'success' };
  }

  /** 设置群级 boundAgentId; weixin-db 群聊必须显式绑定 Agent。 */
  @Post('/setBoundAgent')
  async setBoundAgent(@Body() body: { id: number; agentId: number | null }) {
    if (!body?.id) return { code: 1003, message: 'id is required' };
    try {
      await this.groupService.setBoundAgent(body.id, body.agentId ?? null);
    } catch (err: any) {
      return { code: 1003, message: err?.message || 'setBoundAgent failed' };
    }
    return { code: 1000, message: 'success' };
  }

  /** 设置群级 replyIdentity; weixin-db 群聊必须显式选择回复身份。 */
  @Post('/setReplyIdentity')
  async setReplyIdentity(@Body() body: { id: number; value: 'silent' | 'ai_prefix' | null }) {
    if (!body?.id) return { code: 1003, message: 'id is required' };
    try {
      await this.groupService.setReplyIdentityOverride(body.id, body.value ?? null);
    } catch (err: any) {
      return { code: 1003, message: err?.message || 'setReplyIdentity failed' };
    }
    return { code: 1000, message: 'success' };
  }

  @Post('/rename')
  async rename(@Body() body: { id: number; roomName: string }) {
    if (!body?.id) return { code: 1003, message: 'id is required' };
    await this.groupService.rename(body.id, body.roomName);
    return { code: 1000, message: 'success' };
  }

  @Post('/delete')
  async delete(@Body() body: { ids: number[] }) {
    if (!Array.isArray(body?.ids) || body.ids.length === 0) {
      return { code: 1003, message: 'ids is required' };
    }
    await this.groupService.deleteByIds(body.ids);
    return { code: 1000, message: 'success' };
  }

  @Post('/sync')
  async sync(@Body() body: { groupId: number }) {
    if (!body?.groupId) return { code: 1003, message: 'groupId is required' };
    try {
      const data = await this.groupService.sync(body.groupId);
      return { code: 1000, data };
    } catch (err: any) {
      const token = err?.message || 'sync-failed';
      const message = ERROR_MESSAGES[token] ?? `同步失败: ${token}`;
      return { code: 1003, message };
    }
  }
}
