// aislop-ignore-file: duplicate-block -- 钉钉 API 调用块结构相似（端点/参数不同）
import type {
  DingTalkLeaveResult,
  DingTalkServiceContext,
} from './dingtalk.types';

interface DingTalkGetUpdateDataResponse {
  errcode: number;
  errmsg: string;
  result?: {
    userid?: string;
    work_date?: string;
    approve_list?: Array<{
      procInst_id?: string;
      tag_name?: string;
      sub_type?: string;
      biz_type?: number;
      begin_time?: string;
      end_time?: string;
      gmt_finished?: string;
      duration?: string;
      duration_unit?: string;
    }>;
  };
}

/**
 * 钉钉请假数据客户端。
 *
 * 使用「获取用户考勤数据」接口（topapi/attendance/getupdatedata），按用户+工作日
 * 返回当天打卡结果与审批单列表；这里只取 biz_type=3（请假）且已审批完成
 * （gmt_finished 非空）的记录，保证结算时不会把审批中的请假误判为请假。
 */
export class DingTalkLeaveClient {
  constructor(private readonly context: DingTalkServiceContext) {}

  async fetchDailyLeaveStatus(
    userId: string,
    workDate: string,
  ): Promise<DingTalkLeaveResult[]> {
    if (!(await this.context.isConfigured())) throw new Error('DingTalk not configured');
    if (!userId) throw new Error('钉钉请假查询 userId 不能为空');

    const token = await this.context.getAccessToken();
    await this.context.rateLimit();
    const res = await fetch(
      `https://oapi.dingtalk.com/topapi/attendance/getupdatedata?access_token=${token}`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          userid: userId,
          work_date: workDate.includes(' ') ? workDate : `${workDate} 00:00:00`,
        }),
      },
    );
    const data = (await res.json()) as DingTalkGetUpdateDataResponse;
    if (data.errcode !== 0) {
      throw new Error(`钉钉请假数据获取失败: ${data.errmsg}`);
    }

    const result = data.result;
    if (!result) return [];
    const approveList = result.approve_list ?? [];

    return approveList
      .filter(
        (approval) =>
          approval.biz_type === 3 &&
          approval.gmt_finished &&
          approval.procInst_id &&
          approval.begin_time &&
          approval.end_time,
      )
      .map((approval) => ({
        userId: result.userid ?? userId,
        workDate,
        procInstId: approval.procInst_id!,
        tagName: approval.tag_name ?? '请假',
        leaveType: approval.sub_type ?? '',
        beginTime: this.parseDingDate(approval.begin_time!),
        endTime: this.parseDingDate(approval.end_time!),
        approvedAt: this.parseDingDate(approval.gmt_finished!),
        duration: approval.duration ?? '',
        durationUnit: approval.duration_unit ?? '',
      }));
  }

  /** 钉钉返回的日期可能是 '2026-08-01' 或 '2026-08-01 09:00:00'，统一按东八区解析。 */
  private parseDingDate(value: string): Date {
    const normalized = value.includes(' ') ? value.replace(' ', 'T') : `${value}T00:00:00`;
    const date = new Date(`${normalized}+08:00`);
    return Number.isNaN(date.getTime()) ? new Date(normalized) : date;
  }
}
