import { ServiceUnavailableException } from '@nestjs/common';
import type {
  DingTalkScheduleItem,
  DingTalkScheduleResult,
  DingTalkServiceContext,
} from './dingtalk.types';

export class DingTalkScheduleClient {
  constructor(private readonly context: DingTalkServiceContext) {}

  /** 批量排班（单次最多200条） */
  async scheduleUsers(
    groupId: number, schedules: DingTalkScheduleItem[], opUserId = 'manager',
  ): Promise<void> {
    if (!(await this.context.isConfigured())) throw new ServiceUnavailableException('钉钉未配置');
    if (schedules.length === 0) return;
    if (schedules.length > 200) {
      throw new Error(`排班单次最多200条，当前 ${schedules.length} 条`);
    }

    const token = await this.context.getAccessToken();
    const body = {
      op_user_id: opUserId,
      group_id: groupId,
      schedules: schedules.map((s) => ({
        userid: s.userid,
        work_date: s.work_date,
        shift_id: s.shift_id,
        is_rest: s.is_rest ?? false,
      })),
    };

    await this.context.rateLimit();
    const res = await fetch(
      `https://oapi.dingtalk.com/topapi/attendance/group/schedule/async?access_token=${token}`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      },
    );
    const data = (await res.json()) as {
      errcode: number; errmsg: string;
    };
    if (data.errcode !== 0) {
      throw new Error(`钉钉排班失败: ${data.errmsg} (code=${data.errcode})`);
    }
    this.context.logger.log(`钉钉排班成功: groupId=${groupId}, ${schedules.length} 条`);
  }

  /** 查询指定用户的排班信息（7天内，最多50人） */
  async queryScheduleByUsers(
    userIds: string[], fromDate: number, toDate: number, opUserId = 'manager',
  ): Promise<DingTalkScheduleResult[]> {
    if (!(await this.context.isConfigured())) throw new ServiceUnavailableException('钉钉未配置');
    const token = await this.context.getAccessToken();

    await this.context.rateLimit();
    const res = await fetch(
      `https://oapi.dingtalk.com/topapi/attendance/schedule/listbyusers?access_token=${token}`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          op_user_id: opUserId,
          userids: userIds.join(','),
          from_date_time: fromDate,
          to_date_time: toDate,
        }),
      },
    );
    const data = (await res.json()) as {
      errcode: number; errmsg: string;
      result?: Array<{
        userid: string; work_date: string; shift_id: number;
        is_rest: string; check_type: string; plan_check_time: string;
        group_id: number; id: number;
      }>;
    };
    if (data.errcode !== 0) {
      throw new Error(`钉钉查询排班失败: ${data.errmsg} (code=${data.errcode})`);
    }
    return (data.result ?? []).map((r) => ({
      userid: r.userid,
      work_date: r.work_date,
      shift_id: r.shift_id,
      is_rest: r.is_rest,
      check_type: r.check_type,
      plan_check_time: r.plan_check_time,
      group_id: r.group_id,
      id: r.id,
    }));
  }
}
