import { Body, Controller, Get, Inject, Param, Post, Query } from '@midwayjs/core';
import { ApiQuery, ApiTags } from '@midwayjs/swagger';
import { ContactApplyService } from '../../service/users/contactApply.service';
import { get, isArray, omit, pick } from 'lodash';
import { Validate } from '@midwayjs/validate';
import { ServiceError, ErrorCode } from '../../error/service.error';
import { MessageService } from '../../service/system/message.service';
import { Context } from '@midwayjs/koa';
import { ESService } from '../../service/elasticsearch/es.service';

const namePrefix = '联系方式';
@ApiTags(['联系方式'])
@Controller('/contactApply', { tagName: namePrefix })
export class ContactApplyController {
  @Inject()
  ctx: Context;
  @Inject()
  service: ContactApplyService;
  @Inject()
  msgService: MessageService;
  @Inject()
  esService: ESService;

  @Post('/examine', { routerName: `审核${namePrefix}` })
  @ApiTags('信息审核')
  @ApiQuery({ name: 'examine' })
  async examine(@Body('id') id: number, @Body('status') status: string, @Body('contacts') inputContacts: object) {
    if (!id || !status) throw new ServiceError(ErrorCode.BODY_ERROR);
    const originData = await this.service.fetch({ id });
    if (!originData) throw new ServiceError(ErrorCode.DATA_NOT_FOUND); // 抛出异常,未找到要审核的数据
    const user = get(this.ctx, 'user');
    const exam_admin = get(user, 'id');
    if (!exam_admin) throw new ServiceError(ErrorCode.ADMIN_NOT_LOGIN); // 抛出异常,无管理员
    // 需要查询当前管理员所在部门是否有审核的能力,再查询可见的数据
    const source = await this.service.checkUserSourceRange();
    const hasPermission = source.find(f => f === get(originData, 'source'));
    if (!hasPermission) throw new ServiceError(ErrorCode.CONTACTAPPLY_ADMIN_NO_PERMISSION); // 抛出异常,当前管理人员无审核该数据的权限
    const result = await this.service.update({ id }, { status, exam_admin });
    if (status === '1') {
      try {
        // 审核成功的发送通知, 生成message,然后发送消息
        const messageData = await this.service.successMessage(id, inputContacts);
        /**创建消息数据 */
        const messageResult = await this.msgService.create(messageData);
        const msgId = get(messageResult, 'id');
        this.msgService.toSendMsg(msgId);
      } catch (error) {
        console.error('审核联系方式 消息创建失败');
      }
    }
    return result;
  }

  @Get('/')
  @ApiTags('列表查询')
  @ApiQuery({ name: 'query' })
  async index(@Query() query: object) {
    const qobj: any = omit(query, ['skip', 'limit']);
    const others = pick(query, ['skip', 'limit']);
    // 需要查询当前管理员所在部门是否有审核的能力,再查询可见的数据
    const source = await this.service.checkUserSourceRange();
    if (isArray(source) && source.length > 0) qobj.source = source;
    const { data, total } = await this.service.query(qobj, others, { source: this.service.Opera.In });
    const nd = await this.service.dealData(data);
    return { data: nd, total };
  }

  @Post('/', { routerName: `申请${namePrefix}` })
  @ApiTags('创建数据')
  @Validate()
  async create(@Body() data: object) {
    const skipCheckList = this.service.skipCheckList;
    /**
     * 根据keyword去查询 来源数据 与 当前用户 填写的数据 是否有达到4星匹配度的数据,没有直接拒绝
     * 因为词库很少,所以很简单就能达到.要是没达到,那就说是真的差太多了
     */
    const source = get(data, 'source');
    let source_id: any = get(data, 'source_id');
    if (source_id) source_id = parseInt(source_id);
    // 检查当前 来源数据是否是当前用户的.是当前用户的也不需要继续了,自己找自己么?
    const otherData = await this.service.searchCompleteData(source, source_id);
    const sourceData = get(otherData, 'sourceData');
    const source_user = get(sourceData, 'user');
    const user_id = get(this.ctx, 'user.id');
    if (user_id === source_user) throw new ServiceError(ErrorCode.CONTACTAPPLY_IS_THIS_USER_DATA); // 抛出异常: 来源数据是当前用户的数据
    /**组织数据,填充联系方式申请表:将被申请方的id填充 */
    const userData = get(otherData, 'userData');
    // 如果是在跳过检查列表中的申请,则不需要target_user.直接由管理员审核
    if (!skipCheckList.includes(source)) {
      if (!userData) throw new ServiceError(ErrorCode.CONTACTAPPLY_TARGET_USER_NOT_FOUND);
      const target_user = get(userData, 'id');
      data['target_user'] = target_user;
    }
    // 检查是否有未审核的申请
    await this.service.checkHasApply(data);
    // 判断是否是 跳过检查列表 中的数据,如果在跳过检查列表,则不需要计算匹配度,就是单纯要信息
    if (!skipCheckList.includes(source)) {
      // 需求,供给,项目,成果都是用name去查询匹配度
      const keyword = get(sourceData, 'name');
      // 没有keyword,无法计算匹配度,不用继续往下了.
      if (!keyword) throw new ServiceError(ErrorCode.CONTACTAPPLY_NO_KEYWORD); //抛出异常: 无关键词,无法进行匹配计算
      // 查询匹配度
      const result = await this.esService.getCS(keyword, source);
      if (!result) throw new ServiceError(ErrorCode.CONTACTAPPLY_MATCHING_NOT_ENOUGH); // 抛出异常,无匹配度到4星,无法进行预约
    }
    /**创建申请数据 */
    const dbData = await this.service.create(data);
    /**找到应该接收该消息的管理员:通过消息类型分配的部门,发送给部门下的所有管理员
     * 1.找到 管该类型数据的部门下的管理员id
     */
    const adminIds = await this.service.getSourceDept(source);
    // TODO: 需要确认,超级管理员是否需要处理这个问题,或者指定管理员兜底. 如果出现指定部门下没有人员的情况.没有兜底管理员则此数据不会有任何通知
    if (!adminIds) return; // 部门下无管理人员,请联系平台维护人员
    try {
      /**给这些管理员发送消息,通知他们去个人审核这个信息 */
      const messageData = await this.service.getAdminToExamData(data, adminIds);
      /**创建消息数据 */
      const messageResult = await this.msgService.create(messageData);
      const msgId = get(messageResult, 'id');
      this.msgService.toSendMsg(msgId);
    } catch (error) {
      console.error('申请联系方式 消息创建失败');
    }
    return dbData;
  }
}
