import { Inject, Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { BaseSysDepartmentEntity } from '../../base/entity/sys/department';
import { BasicdataIotEntity } from '../entity/iot';
import { BaseSysPermsService } from '../../base/service/sys/perms';
import { BaseSysParamEntity } from '../../base/entity/sys/param';
import * as _ from 'lodash';

/**
 * 数据源定义信息服务
 */
@Provide()
export class BasicdataIotService extends BaseService {
  @InjectEntityModel(BasicdataIotEntity)
  basicdataIotEntity: Repository<BasicdataIotEntity>;

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

  @InjectEntityModel(BaseSysParamEntity)
  baseSysParamEntity: Repository<BaseSysParamEntity>;

  @Inject()
  baseSysPermsService: BaseSysPermsService;

  @Inject()
  ctx;

  /**
   * 获得部门+站点合并树（遵循 Cool 数据权限规范）
   */
  async sitelist() {
    const { userId, username } = this.ctx.admin;

    // 超管不受限
    const isAdmin = username === 'admin';
    let deptIds: any[] = [];

    if (!isAdmin) {
      deptIds = await this.baseSysPermsService.departmentIds(userId);
      // 没配部门权限时给个必定为空的值，防止查出全库
      if (_.isEmpty(deptIds)) deptIds = [null];
    }

    const sql = `
    (
      SELECT
        a.id           AS a_id,
        a.tenantId     AS a_tenantId,
        a.name         AS a_name,
        a.parentId     AS a_parentId,
        a.orderNum     AS a_orderNum
      FROM base_sys_department a
      ${isAdmin ? 'WHERE 1=1' : 'WHERE a.id IN (?)'}
    )
    UNION ALL
    (
      SELECT
        b.businessId   AS a_id,
        a.tenantId     AS a_tenantId,
        b.businessName AS a_name,
        b.departmentId AS a_parentId,
        COALESCE(a.orderNum, 999) AS a_orderNum
      FROM t_basicdata_site b
      LEFT JOIN base_sys_department a ON b.departmentId = a.id
      ${!isAdmin ? 'WHERE b.departmentId IN (?)' : ''}
    )
    ORDER BY a_orderNum ASC
  `;

    // nativeQuery 第二个参数必须显式传参数组
    const params = isAdmin ? [] : [deptIds, deptIds];

    return this.nativeQuery(sql, params);
  }

  /**
   * 监控设备查询
   */
  async getYsDevices(businessId: string) {
    // 修复原先key、secret取值颠倒bug + 增加await
    // const appKey_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appKey' });
    // departmentId 是数字，尝试转换；转换失败赋值 null
    const deptId = /^\d+$/.test(businessId) ? Number(businessId) : null;
    const qb = this.basicdataIotEntity.createQueryBuilder('a')
      .select([
        'a.id',
        'a.iotCode',
        'a.iotName',
        'a.iotTypeCode',
        'a.businessType',
        'a.businessId',
        'a.departmentId',
        'a.iotKey',
        'a.iotSecret',
        'a.iotChanel',
        'a.installLocation',
        'a.protocol'
      ])
      .where('a.iotTypeCode IN (:...typeIds)', {
        typeIds: ['萤石云固定监控', '萤石云车载监控'],
      });
    if (deptId !== null) {
      qb.andWhere('(a.businessId = :businessId OR a.departmentId = :deptId)', {
        businessId,
        deptId
      });
    } else {
      qb.andWhere('a.businessId = :businessId', { businessId });
    }
    const result = await qb.orderBy('a.iotName', 'ASC').getMany();
    return result;
  }

  /**
   * 递归获取部门及其所有子部门 ID
   */
  async getDepartmentAndChildren(deptId: number): Promise<number[]> {
    const result: number[] = [deptId];
    const findChildren = async (pid: number) => {
      const children = await this.baseSysDepartmentEntity
        .createQueryBuilder('d')
        .select('d.id')
        .where('d.parentId = :pid', { pid })
        .getMany();
      for (const c of children) {
        result.push(c.id);
        await findChildren(c.id);
      }
    };
    await findChildren(deptId);
    return result;
  }  

}