import { Inject, Provide } from '@midwayjs/decorator';
import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { BaseSysUserEntity } from '../../entity/sys/user';
import { BaseSysPermsService } from './perms';
import * as _ from 'lodash';
import { BaseSysUserRoleEntity } from '../../entity/sys/user_role';
import * as md5 from 'md5';
import { BaseSysDepartmentEntity } from '../../entity/sys/department';
import { CacheManager } from '@midwayjs/cache';

/**
 * 系统用户
 */
@Provide()
export class BaseSysUserService extends BaseService {
  @InjectEntityModel(BaseSysUserEntity)
  baseSysUserEntity: Repository<BaseSysUserEntity>;

  @InjectEntityModel(BaseSysUserRoleEntity)
  baseSysUserRoleEntity: Repository<BaseSysUserRoleEntity>;

  @InjectEntityModel(BaseSysDepartmentEntity)
  baseSysDepartmentEntity: Repository<BaseSysDepartmentEntity>;

  @Inject()
  cacheManager: CacheManager;

  @Inject()
  baseSysPermsService: BaseSysPermsService;

  @Inject()
  ctx;

  /**
   * 分页查询
   * @param query
   */
  async page(query) {
    const { keyWord, status, departmentIds = [] } = query;
    const permsDepartmentArr = await this.baseSysPermsService.departmentIds(
      this.ctx.admin.userId
    ); // 部门权限
    const sql = `
        SELECT
            a.id,a.name,a."nickName",a."headImg",a.email,a.remark,a.status,a."createTime",a."updateTime",a.username,a.phone,a."departmentId",
            string_agg(c.name,',') AS "roleName",
            d.name as "departmentName"
        FROM
            base_sys_user a
            LEFT JOIN base_sys_user_role b ON a.id = b."userId"
            LEFT JOIN base_sys_role c ON b."roleId" = c.id
            LEFT JOIN base_sys_department d on a."departmentId" = d.id
        WHERE 1 = 1
        and a.username != 'admin'
            ${this.setSql(
              !_.isEmpty(departmentIds),
              'and a."departmentId" = ANY ($1)',
              [departmentIds]
            )}
            ${this.setSql(
              status,
              !_.isEmpty(departmentIds)
                ? 'and a.status = $2'
                : 'and a.status = $1',
              [status]
            )}
            ${this.setSql(
              keyWord,
              !_.isEmpty(departmentIds)
                ? status !== undefined
                  ? 'and (a.name LIKE $3 or a.username LIKE $4)'
                  : 'and (a.name LIKE $2 or a.username LIKE $3)'
                : status !== undefined
                ? 'and (a.name LIKE $2 or a.username LIKE $3)'
                : 'and (a.name LIKE $1 or a.username LIKE $2)',
              [`%${keyWord}%`, `%${keyWord}%`]
            )}
            ${this.setSql(
              this.ctx.admin.username !== 'admin',
              !_.isEmpty(departmentIds)
                ? status !== undefined
                  ? keyWord !== undefined
                    ? 'and a."departmentId" = ANY ($5)'
                    : 'and a."departmentId" = ANY ($3)'
                  : keyWord !== undefined
                  ? 'and a."departmentId" = ANY ($4)'
                  : 'and a."departmentId" = ANY ($2)'
                : status !== undefined
                ? keyWord !== undefined
                  ? 'and a."departmentId" = ANY ($4)'
                  : 'and a."departmentId" = ANY ($2)'
                : keyWord !== undefined
                ? 'and a."departmentId" = ANY ($3)'
                : 'and a."departmentId" = ANY ($1)',

              [!_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [null]]
            )}
        GROUP BY a.id,d.name
        `;
    return this.sqlRenderPage(sql, query);
  }

  /**
   * 移动部门
   * @param departmentId
   * @param userIds
   */
  async move(departmentId, userIds) {
    await this.baseSysUserEntity
      .createQueryBuilder()
      .update()
      .set({ departmentId })
      .where('id = ANY (:userIds)', { userIds })
      .execute();
  }

  /**
   * 获得个人信息
   */
  async person() {
    const info = await this.baseSysUserEntity.findOneBy({
      id: this.ctx.admin?.userId,
    });
    delete info?.password;
    return info;
  }

  /**
   * 更新用户角色关系
   * @param user
   */
  async updateUserRole(user) {
    if (_.isEmpty(user.roleIdList)) {
      return;
    }
    if (user.username === 'admin') {
      throw new CoolCommException('非法操作~');
    }
    await this.baseSysUserRoleEntity.delete({ userId: user.id });
    if (user.roleIdList) {
      for (const roleId of user.roleIdList) {
        await this.baseSysUserRoleEntity.save({ userId: user.id, roleId });
      }
    }
    await this.baseSysPermsService.refreshPerms(user.id);
  }

  /**
   * 新增
   * @param param
   */
  async add(param) {
    const exists = await this.baseSysUserEntity.findOneBy({
      username: param.username,
    });
    if (!_.isEmpty(exists)) {
      throw new CoolCommException('用户名已经存在~');
    }
    param.password = md5(param.password);
    await this.baseSysUserEntity.save(param);
    await this.updateUserRole(param);
    return param.id;
  }

  /**
   * 根据ID获得信息
   * @param id
   */
  public async info(id) {
    const info = await this.baseSysUserEntity.findOneBy({ id });
    const userRoles = await this.nativeQuery(
      'select a."roleId" from base_sys_user_role a where a."userId" = $1',
      [id]
    );
    const department = await this.baseSysDepartmentEntity.findOneBy({
      id: info.departmentId,
    });
    if (info) {
      delete info.password;
      if (userRoles) {
        info.roleIdList = userRoles.map(e => {
          return parseInt(e.roleId);
        });
      }
    }
    delete info.password;
    if (department) {
      info.departmentName = department.name;
    }
    return info;
  }

  /**
   * 修改个人信息
   * @param param
   */
  public async personUpdate(param) {
    param.id = this.ctx.admin.userId;
    if (!_.isEmpty(param.password)) {
      param.password = md5(param.password);
      const userInfo = await this.baseSysUserEntity.findOneBy({ id: param.id });
      if (!userInfo) {
        throw new CoolCommException('用户不存在');
      }
      param.passwordV = userInfo.passwordV + 1;
      await this.cacheManager.set(
        `admin:passwordVersion:${param.id}`,
        param.passwordV
      );
    } else {
      delete param.password;
    }
    await this.baseSysUserEntity.save(param);
  }

  /**
   * 修改
   * @param param 数据
   */
  async update(param) {
    if (param.id && param.username === 'admin') {
      throw new CoolCommException('非法操作~');
    }
    if (!_.isEmpty(param.password)) {
      param.password = md5(param.password);
      const userInfo = await this.baseSysUserEntity.findOneBy({ id: param.id });
      if (!userInfo) {
        throw new CoolCommException('用户不存在');
      }
      param.passwordV = userInfo.passwordV + 1;
      await this.cacheManager.set(
        `admin:passwordVersion:${param.id}`,
        param.passwordV
      );
    } else {
      delete param.password;
    }
    if (param.status === 0) {
      await this.forbidden(param.id);
    }
    await this.baseSysUserEntity.save(param);
    await this.updateUserRole(param);
  }

  /**
   * 禁用用户
   * @param userId
   */
  async forbidden(userId) {
    await this.cacheManager.del(`admin:token:${userId}`);
  }
}
