import { Injectable, Logger } from '@nestjs/common';
import { DingtalkAuthService } from './dingtalk-auth.service';
import axios from 'axios';

@Injectable()
export class DingtalkHrmService {
  private readonly logger = new Logger(DingtalkHrmService.name);

  constructor(private authService: DingtalkAuthService) {}

  /**
   * 获取在职员工ID列表
   * 对应Python: DingtalkUtils.get_employee_id_on_job()
   */
  async getOnJobEmployeeIds(): Promise<string[]> {
    const token = await this.authService.getAccessToken();
    const employeeList: string[] = [];
    let offset = 0;

    while (true) {
      this.logger.log(`[API→] POST /topapi/smartwork/hrm/employee/queryonjob offset=${offset}`);
      const resp = await axios.post(
        'https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/queryonjob',
        { status_list: '2,3,5,-1', offset, size: 50 },
        { params: { access_token: token } },
      );
      this.logger.log(`[API←] queryonjob errcode=${resp.data.errcode} count=${resp.data.result?.data_list?.length || 0} next_cursor=${resp.data.result?.next_cursor || 'null'}`);

      employeeList.push(...resp.data.result.data_list);

      if (!resp.data.result.next_cursor) break;
      offset = resp.data.result.next_cursor;
    }

    this.logger.log(`[API] getOnJobEmployeeIds 总计 ${employeeList.length} 人`);
    return employeeList;
  }

  /**
   * 根据ID批量获取员工详细信息
   * 对应Python: DingtalkUtils.get_employee_info_by_id()
   */
  async getEmployeeInfoByIds(userIds: string[]): Promise<Record<string, any>> {
    const token = await this.authService.getAccessToken();
    const result: Record<string, any> = {};

    // 每100个一批
    const chunks: string[][] = [];
    for (let i = 0; i < userIds.length; i += 100) {
      chunks.push(userIds.slice(i, i + 100));
    }

    for (const chunk of chunks) {
      this.logger.log(`[API→] POST /topapi/smartwork/hrm/employee/v2/list batch=${chunk.length}人`);
      const resp = await axios.post(
        'https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/v2/list',
        {
          agentid: this.authService.agentId,
          userid_list: chunk.join(','),
        },
        { params: { access_token: token } },
      );
      this.logger.log(`[API←] employee/v2/list errcode=${resp.data.errcode} returned=${resp.data.result?.length || 0}`);

      for (const employee of resp.data.result) {
        result[employee.userid] = employee;
      }
    }

    this.logger.log(`[API] getEmployeeInfoByIds 总计 ${Object.keys(result).length} 人`);
    return result;
  }

  /**
   * 获取部门列表
   * 对应Python: DingtalkUtils.get_department_list()
   */
  async getDepartmentList(deptId: number): Promise<any[]> {
    const token = await this.authService.getAccessToken();

    // 节流 0.3s
    await new Promise((resolve) => setTimeout(resolve, 300));

    this.logger.log(`[API→] POST /topapi/v2/department/listsub dept_id=${deptId}`);
    const resp = await axios.post(
      'https://oapi.dingtalk.com/topapi/v2/department/listsub',
      { dept_id: deptId },
      { params: { access_token: token } },
    );
    this.logger.log(`[API←] department/listsub dept_id=${deptId} errcode=${resp.data.errcode} count=${resp.data.result?.length || 0}`);

    return resp.data.result || [];
  }

  /**
   * 尝试用老版 API 一次性获取所有部门（fetch_child=true）
   * 如果老版 API 不可用，返回 null
   */
  private async tryGetAllDepartmentsV1(): Promise<any[] | null> {
    try {
      const token = await this.authService.getAccessToken();
      this.logger.log('[API→] GET /department/list?id=1&fetch_child=true (v1)');
      const resp = await axios.get(
        'https://oapi.dingtalk.com/department/list',
        { params: { access_token: token, id: 1, fetch_child: true } },
      );
      this.logger.log(`[API←] department/list (v1) errcode=${resp.data.errcode} count=${resp.data.department?.length || 0}`);

      if (resp.data.errcode === 0 && Array.isArray(resp.data.department)) {
        return resp.data.department;
      }
      return null;
    } catch {
      this.logger.warn('老版部门 API 不可用，回退到递归方式');
      return null;
    }
  }

  /**
   * 从 v1 API 的扁平部门列表构建部门全称映射
   */
  private buildDeptNamesFromV1(departments: any[]): Record<number, { name: string; firstLevel: string }> {
    const deptMap = new Map<number, { id: number; name: string; parentid: number }>();
    for (const d of departments) {
      deptMap.set(d.id, { id: d.id, name: d.name, parentid: d.parentid });
    }

    const result: Record<number, { name: string; firstLevel: string }> = {};

    const getFullName = (id: number): string => {
      const dept = deptMap.get(id);
      if (!dept || dept.parentid === 1 || !deptMap.has(dept.parentid)) return dept?.name || '';
      return `${getFullName(dept.parentid)}-${dept.name}`;
    };

    const getFirstLevel = (id: number): string => {
      const dept = deptMap.get(id);
      if (!dept) return '';
      if (dept.parentid === 1) return dept.name;
      return getFirstLevel(dept.parentid);
    };

    for (const d of departments) {
      if (d.id === 1) continue; // 跳过根部门
      result[d.id] = {
        name: getFullName(d.id),
        firstLevel: getFirstLevel(d.id),
      };
    }

    return result;
  }

  /**
   * 获取所有部门全称
   * 使用 v1 API 一次请求获取全部部门，本地构建全称
   */
  async getDepartmentFullNames(): Promise<Record<number, { name: string; firstLevel: string }>> {
    const v1Departments = await this.tryGetAllDepartmentsV1();
    if (v1Departments && v1Departments.length > 0) {
      this.logger.log(`v1 API 获取到 ${v1Departments.length} 个部门`);
      return this.buildDeptNamesFromV1(v1Departments);
    }

    // v1 不可用时回退到递归
    this.logger.warn('v1 部门 API 不可用，回退到递归方式');
    const departList: Record<number, { name: string; firstLevel: string }> = {};
    const level1Deps = await this.getDepartmentList(1);
    for (const dep1 of level1Deps) {
      departList[dep1.dept_id] = { name: dep1.name, firstLevel: dep1.name };
      const level2Deps = await this.getDepartmentList(dep1.dept_id);
      for (const dep2 of level2Deps) {
        departList[dep2.dept_id] = { name: `${dep1.name}-${dep2.name}`, firstLevel: dep1.name };
        const level3Deps = await this.getDepartmentList(dep2.dept_id);
        for (const dep3 of level3Deps) {
          departList[dep3.dept_id] = { name: `${dep1.name}-${dep2.name}-${dep3.name}`, firstLevel: dep1.name };
          const level4Deps = await this.getDepartmentList(dep3.dept_id);
          for (const dep4 of level4Deps) {
            departList[dep4.dept_id] = { name: `${dep1.name}-${dep2.name}-${dep3.name}-${dep4.name}`, firstLevel: dep1.name };
          }
        }
      }
    }
    return departList;
  }

  /**
   * 获取所有部门的一级部门映射
   * 对应Python: get_depart_parent_all()
   */
  async getDepartmentParents(): Promise<Record<number, { name: string; firstLevel: string }>> {
    const departList: Record<number, { name: string; firstLevel: string }> = {};

    const level1Deps = await this.getDepartmentList(1);
    for (const dep1 of level1Deps) {
      departList[dep1.dept_id] = { name: dep1.name, firstLevel: dep1.name };

      const level2Deps = await this.getDepartmentList(dep1.dept_id);
      for (const dep2 of level2Deps) {
        departList[dep2.dept_id] = { name: dep2.name, firstLevel: dep1.name };

        const level3Deps = await this.getDepartmentList(dep2.dept_id);
        for (const dep3 of level3Deps) {
          departList[dep3.dept_id] = { name: dep3.name, firstLevel: dep1.name };

          const level4Deps = await this.getDepartmentList(dep3.dept_id);
          for (const dep4 of level4Deps) {
            departList[dep4.dept_id] = { name: dep4.name, firstLevel: dep1.name };
          }
        }
      }
    }

    return departList;
  }
}
