import { DingtalkController } from '../../../../src/modules/organization/dingtalk/dingtalk.controller';
import { FIELD_APPLICATION_FIELDS } from '../../../../src/modules/organization/dingtalk/constants';

describe('DingtalkController', () => {
  const prisma = {} as any;
  const authService = {} as any;
  const hrmService = {} as any;
  const schedulerService = {} as any;
  const repairService = {} as any;
  const annualLeaveInsightService = {} as any;
  const annualLeavePlanAdminService = {
    getPlanSettings: jest.fn(),
    updatePlanSettings: jest.fn(),
  } as any;
  const employeeManagementService = {} as any;

  it('应从钉钉考勤记录中识别并返回 undefined 外勤审批', async () => {
    const yidaService = {
      searchApprovedInstances: jest.fn().mockResolvedValue([
        {
          creatorUserId: 'user001',
          formInstanceId: 'INST001',
          formData: {
            [FIELD_APPLICATION_FIELDS.CREATOR]: '张三',
            [FIELD_APPLICATION_FIELDS.TABLE_FIELD]: [
              {
                [FIELD_APPLICATION_FIELDS.FROM_DATE]: new Date('2026-01-03T09:00:00+08:00').getTime(),
                [FIELD_APPLICATION_FIELDS.TO_DATE]: new Date('2026-01-03T18:00:00+08:00').getTime(),
              },
            ],
          },
        },
      ]),
    };
    const attendanceService = {
      getApproveRecords: jest.fn().mockResolvedValue({
        errcode: 0,
        result: {
          approve_list: [
            { tag_name: '外出', procInst_id: 'WQSQ202601030001-1' },
            { tag_name: '外出', procInst_id: 'undefined-1' },
          ],
        },
      }),
      approveCancel: jest.fn(),
    };

    const controller = new DingtalkController(
      prisma,
      authService,
      hrmService,
      attendanceService as any,
      yidaService as any,
      schedulerService,
      repairService,
      annualLeaveInsightService,
      annualLeavePlanAdminService,
      employeeManagementService,
    );

    const result = await controller.cleanupInvalidFieldApprovals({
      from: '2026-01-01',
      to: '2026-12-31',
      dryRun: true,
    });

    expect(attendanceService.getApproveRecords).toHaveBeenCalledWith('user001', '2026-01-03');
    expect(result).toEqual({
      dryRun: true,
      scannedDays: 1,
      total: 1,
      records: [
        {
          userId: 'user001',
          approveId: 'undefined-1',
          creator: '张三',
          date: '2026-01-03',
          instanceIds: ['INST001'],
        },
      ],
    });
  });

  it('实际清理时应撤销所有去重后的 undefined 外勤审批', async () => {
    const yidaService = {
      searchApprovedInstances: jest.fn().mockResolvedValue([
        {
          creatorUserId: 'user001',
          formInstanceId: 'INST001',
          formData: {
            [FIELD_APPLICATION_FIELDS.CREATOR]: '张三',
            [FIELD_APPLICATION_FIELDS.TABLE_FIELD]: [
              {
                [FIELD_APPLICATION_FIELDS.FROM_DATE]: new Date('2026-01-03T09:00:00+08:00').getTime(),
                [FIELD_APPLICATION_FIELDS.TO_DATE]: new Date('2026-01-03T18:00:00+08:00').getTime(),
              },
            ],
          },
        },
        {
          creatorUserId: 'user001',
          formInstanceId: 'INST002',
          formData: {
            [FIELD_APPLICATION_FIELDS.CREATOR]: '张三',
            [FIELD_APPLICATION_FIELDS.TABLE_FIELD]: [
              {
                [FIELD_APPLICATION_FIELDS.FROM_DATE]: new Date('2026-01-03T10:00:00+08:00').getTime(),
                [FIELD_APPLICATION_FIELDS.TO_DATE]: new Date('2026-01-03T20:00:00+08:00').getTime(),
              },
            ],
          },
        },
      ]),
    };
    const attendanceService = {
      getApproveRecords: jest.fn().mockResolvedValue({
        errcode: 0,
        result: {
          approve_list: [
            { tag_name: '外出', procInst_id: 'undefined-1' },
            { tag_name: '外出', procInst_id: 'undefined-1' },
            { tag_name: '加班', procInst_id: 'undefined-9' },
          ],
        },
      }),
      approveCancel: jest.fn().mockResolvedValue({ errcode: 0 }),
    };

    const controller = new DingtalkController(
      prisma,
      authService,
      hrmService,
      attendanceService as any,
      yidaService as any,
      schedulerService,
      repairService,
      annualLeaveInsightService,
      annualLeavePlanAdminService,
      employeeManagementService,
    );

    const result = await controller.cleanupInvalidFieldApprovals({
      from: '2026-01-01',
      to: '2026-12-31',
      dryRun: false,
    });

    expect(attendanceService.approveCancel).toHaveBeenCalledTimes(1);
    expect(attendanceService.approveCancel).toHaveBeenCalledWith('user001', 'undefined-1');
    expect(result).toMatchObject({
      dryRun: false,
      scannedDays: 1,
      total: 1,
      success: 1,
      failed: 0,
    });
    expect(result.results[0]).toMatchObject({
      userId: 'user001',
      approveId: 'undefined-1',
      status: 'CANCELLED',
    });
    expect(result.results[0].instanceIds).toEqual(['INST001', 'INST002']);
  });

  it('应透传年假计划参数查询与更新请求', async () => {
    annualLeavePlanAdminService.getPlanSettings.mockResolvedValueOnce({ userId: 'user001', year: 2026 });
    annualLeavePlanAdminService.updatePlanSettings.mockResolvedValueOnce({ userId: 'user001', year: 2026, status: '正常' });

    const controller = new DingtalkController(
      prisma,
      authService,
      hrmService,
      {} as any,
      {} as any,
      schedulerService,
      repairService,
      annualLeaveInsightService,
      annualLeavePlanAdminService,
      employeeManagementService,
    );

    const getResult = await controller.getAnnualLeavePlanSettings({ userId: 'user001', year: 2026 });
    const patchResult = await controller.updateAnnualLeavePlanSettings({
      userId: 'user001',
      year: 2026,
      status: '正常',
      adjustmentDays: 1,
      notCountDays: 2,
      recalculate: true,
    });

    expect(annualLeavePlanAdminService.getPlanSettings).toHaveBeenCalledWith('user001', 2026);
    expect(annualLeavePlanAdminService.updatePlanSettings).toHaveBeenCalledWith({
      userId: 'user001',
      year: 2026,
      status: '正常',
      adjustmentDays: 1,
      notCountDays: 2,
      recalculate: true,
    });
    expect(getResult).toEqual({ userId: 'user001', year: 2026 });
    expect(patchResult).toEqual({ userId: 'user001', year: 2026, status: '正常' });
  });
});
