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

const YIDA_API_BASE = 'https://api.dingtalk.com/v1.0/yida';
const YIDA_ADVANCED_QUERY_PATH = '/forms/instances/advances/queryAll';
const YIDA_INSERT_OR_UPDATE_PATH = '/forms/instances/insertOrUpdate';
const YIDA_OPERATION_RECORDS_PATH = '/processes/operationRecords';

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

  constructor(private authService: DingtalkAuthService) {}

  /**
   * 查询宜搭表单数据（自动分页）
   * 对应 Python: DingtalkUtils.search_yidaform()
   * 使用“高级查询条件二代”接口，保持与原始脚本一致。
   */
  async searchForm(
    formUuid: string,
    searchCondition: string,
    modifiedFromTime?: string,
    modifiedToTime?: string,
    originatorId?: string,
  ): Promise<any[]> {
    const headers = await this.authService.getNewApiHeaders();
    const result: any[] = [];
    let pageNumber = 1;

    while (true) {
      try {
        const body: any = {
          pageNumber,
          formUuid,
          appType: this.authService.appType,
          searchCondition,
          orderConfigJson: JSON.stringify({ gmt_modified: '+' }),
          systemToken: this.authService.systemToken,
          pageSize: 100,
          userId: this.authService.operatorId,
        };

        // 宜搭要求 yyyy-MM-DD 或 yyyy-MM-DD HH:mm:ss 格式，前端 datetime-local 传 "T" 分隔符需替换
        if (modifiedFromTime) {
          let from = modifiedFromTime.replace('T', ' ');
          if (from.length === 10) from += ' 00:00:00'; // 纯日期补时间
          body.modifiedFromTimeGMT = from;
        }
        if (modifiedToTime) {
          let to = modifiedToTime.replace('T', ' ');
          if (to.length === 10) to += ' 23:59:59'; // 纯日期补到当天末尾
          body.modifiedToTimeGMT = to;
        }
        if (originatorId) body.originatorId = originatorId;

        this.logger.log(`[API→] POST ${YIDA_ADVANCED_QUERY_PATH} page=${pageNumber} formUuid=${formUuid}${originatorId ? ` originatorId=${originatorId}` : ''}${body.modifiedFromTimeGMT ? ` from=${body.modifiedFromTimeGMT}` : ''}${body.modifiedToTimeGMT ? ` to=${body.modifiedToTimeGMT}` : ''}`);
        const resp = await axios.post(
          `${YIDA_API_BASE}${YIDA_ADVANCED_QUERY_PATH}`,
          body,
          { headers },
        );
        this.logger.log(`[API←] searchForm page=${pageNumber} totalCount=${resp.data.totalCount} returned=${resp.data.data?.length || 0}`);

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

        const pages = Math.ceil(resp.data.totalCount / 100);
        pageNumber++;
        if (pageNumber > pages) break;
      } catch (error: any) {
        this.logger.error(`searchForm Error: ${error.message} response=${JSON.stringify(error.response?.data || {}).slice(0, 500)}`);
        throw error;
      }
    }

    return result;
  }

  /**
   * 查询审批通过的宜搭流程实例
   * 与 Python 原版一致：用高级查询条件过滤 processApprovedResult=agree
   */
  async searchApprovedInstances(
    formUuid: string,
    modifiedFromTime?: string,
    modifiedToTime?: string,
    originatorId?: string,
  ): Promise<any[]> {
    const searchCondition = JSON.stringify([{
      key: 'processApprovedResult',
      value: ['agree'],
      type: 'ARRAY',
      operator: 'in',
      componentName: 'SelectField',
    }]);

    const result = await this.searchForm(formUuid, searchCondition, modifiedFromTime, modifiedToTime, originatorId);
    this.logger.log(`[searchApprovedInstances] 审批通过: ${result.length}`);
    return result;
  }

  /**
   * 创建或更新宜搭表单数据
   * 对应Python: DingtalkUtils.create_or_update_yidaform()
   */
  async createOrUpdateForm(
    formUuid: string,
    searchCondition: string,
    formDataJson: string,
  ): Promise<any> {
    const headers = await this.authService.getNewApiHeaders();

    try {
      this.logger.log(`[API→] POST ${YIDA_INSERT_OR_UPDATE_PATH} formUuid=${formUuid}`);
      const resp = await axios.post(
        `${YIDA_API_BASE}${YIDA_INSERT_OR_UPDATE_PATH}`,
        {
          noExecuteExpression: false,
          systemToken: this.authService.systemToken,
          formUuid,
          userId: this.authService.operatorId,
          appType: this.authService.appType,
          searchCondition,
          formDataJson,
        },
        { headers },
      );
      this.logger.log(`[API←] insertOrUpdate result: ${JSON.stringify(resp.data).slice(0, 200)}`);

      return resp.data;
    } catch (error: any) {
      this.logger.error(`createOrUpdateForm Error: ${error.message} response=${JSON.stringify(error.response?.data || {}).slice(0, 500)}`);
      throw error;
    }
  }

  /**
   * 根据实例ID查询表单数据
   * 对应Python: DingtalkUtils.get_instance_by_id()
   */
  async getInstanceById(instanceId: string): Promise<any> {
    const headers = await this.authService.getNewApiHeaders();

    try {
      this.logger.log(`[API→] GET /forms/instances/${instanceId}`);
      const resp = await axios.get(
        `${YIDA_API_BASE}/forms/instances/${instanceId}`,
        {
          params: {
            systemToken: this.authService.systemToken,
            userId: this.authService.operatorId,
            appType: this.authService.appType,
          },
          headers,
        },
      );
      this.logger.log(`[API←] getInstance ${instanceId} keys=${JSON.stringify(Object.keys(resp.data || {}))} data=${JSON.stringify(resp.data).slice(0, 500)}`);

      return resp.data;
    } catch (error: any) {
      this.logger.error(`getInstanceById Error: ${error.message} response=${JSON.stringify(error.response?.data || {}).slice(0, 500)}`);
      throw error;
    }
  }

  /**
   * 查询流程操作记录（审批链）
   * 对应 Python: YidaService.get_operation_records()
   */
  async getOperationRecords(processInstanceId: string): Promise<any[]> {
    const headers = await this.authService.getNewApiHeaders();

    try {
      this.logger.log(`[API→] GET ${YIDA_OPERATION_RECORDS_PATH} processInstanceId=${processInstanceId}`);
      const resp = await axios.get(
        `${YIDA_API_BASE}${YIDA_OPERATION_RECORDS_PATH}`,
        {
          params: {
            appType: this.authService.appType,
            systemToken: this.authService.systemToken,
            userId: this.authService.operatorId,
            language: 'zh_CN',
            processInstanceId,
          },
          headers,
        },
      );

      const records = resp.data?.result || [];
      this.logger.log(`[API←] getOperationRecords processInstanceId=${processInstanceId} records=${records.length}`);
      return records;
    } catch (error: any) {
      this.logger.error(`getOperationRecords Error: ${error.message} response=${JSON.stringify(error.response?.data || {}).slice(0, 500)}`);
      throw error;
    }
  }
}
