import { DingtalkRepairService } from '../../../../src/modules/organization/dingtalk/dingtalk-repair.service';
import { FIELD_APPLICATION_FIELDS, OVERTIME_FIELDS } from '../../../../src/modules/organization/dingtalk/constants';

describe('DingtalkRepairService', () => {
  it('应按 undefined-* 通配模式预览外勤错误审批', async () => {
    const yidaService = {
      searchApprovedInstances: jest.fn().mockResolvedValue([
        {
          creatorUserId: 'user001',
          formInstanceId: 'INST001',
          serialNumber: 'FIELD001',
          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: 'undefined-1' },
            { tag_name: '外出', procInst_id: 'FIELD001-1' },
            { tag_name: '加班', procInst_id: 'undefined-9' },
          ],
        },
      }),
      approveCancel: jest.fn(),
    };

    const service = new DingtalkRepairService(yidaService as any, attendanceService as any);
    const result = await service.cancelApprovals({
      taskCode: 'DINGTALK_FIELD_APPLICATION',
      userId: 'user001',
      approveId: 'undefined-*',
      fromTime: '2026-01-01',
      toTime: '2026-01-31',
      dryRun: true,
    });

    expect(result.success).toBe(true);
    expect(result.processedCount).toBe(1);
    expect(result.details?.records).toEqual([
      expect.objectContaining({
        userId: 'user001',
        approveId: 'undefined-1',
        creator: '张三',
        serialNumbers: ['FIELD001'],
      }),
    ]);
    expect(attendanceService.approveCancel).not.toHaveBeenCalled();
  });

  it('精确审批号未命中时不应伪造撤销记录', async () => {
    const yidaService = {
      searchApprovedInstances: jest.fn().mockResolvedValue([
        {
          creatorUserId: 'user002',
          formInstanceId: 'INST002',
          serialNumber: 'OT001',
          formData: {
            [OVERTIME_FIELDS.CREATOR]: '李四',
            [OVERTIME_FIELDS.TABLE_FIELD]: [
              {
                [OVERTIME_FIELDS.FROM_DATE]: new Date('2026-03-10T18:00:00+08:00').getTime(),
                [OVERTIME_FIELDS.TO_DATE]: new Date('2026-03-10T21:00:00+08:00').getTime(),
              },
            ],
          },
        },
      ]),
    };
    const attendanceService = {
      getApproveRecords: jest.fn().mockResolvedValue({
        errcode: 0,
        result: {
          approve_list: [{ tag_name: '加班', procInst_id: 'OT20260310009-1' }],
        },
      }),
      approveCancel: jest.fn(),
    };

    const service = new DingtalkRepairService(yidaService as any, attendanceService as any);
    const result = await service.cancelApprovals({
      taskCode: 'DINGTALK_OVERTIME',
      userId: 'user002',
      approveId: 'OT20260310001-1',
      fromTime: '2026-03-01',
      toTime: '2026-03-31',
      dryRun: false,
    });

    expect(result.success).toBe(true);
    expect(result.processedCount).toBe(0);
    expect(result.details?.records).toEqual([]);
    expect(attendanceService.approveCancel).not.toHaveBeenCalled();
  });

  it('应在精确审批号真实命中后执行撤销', async () => {
    const yidaService = {
      searchApprovedInstances: jest.fn().mockResolvedValue([
        {
          creatorUserId: 'user002',
          formInstanceId: 'INST002',
          serialNumber: 'OT001',
          formData: {
            [OVERTIME_FIELDS.CREATOR]: '李四',
            [OVERTIME_FIELDS.TABLE_FIELD]: [
              {
                [OVERTIME_FIELDS.FROM_DATE]: new Date('2026-03-10T18:00:00+08:00').getTime(),
                [OVERTIME_FIELDS.TO_DATE]: new Date('2026-03-10T21:00:00+08:00').getTime(),
              },
            ],
          },
        },
      ]),
    };
    const attendanceService = {
      getApproveRecords: jest.fn().mockResolvedValue({
        errcode: 0,
        result: {
          approve_list: [
            { tag_name: '加班', procInst_id: 'OT20260310001-1' },
            { tag_name: '外出', procInst_id: 'OT20260310001-1' },
          ],
        },
      }),
      approveCancel: jest.fn().mockResolvedValue({ errcode: 0, errmsg: 'ok' }),
    };

    const service = new DingtalkRepairService(yidaService as any, attendanceService as any);
    const result = await service.cancelApprovals({
      taskCode: 'DINGTALK_OVERTIME',
      userId: 'user002',
      approveId: 'OT20260310001-1',
      fromTime: '2026-03-01',
      toTime: '2026-03-31',
      dryRun: false,
    });

    expect(result.success).toBe(true);
    expect(result.processedCount).toBe(1);
    expect(result.details?.records).toEqual([
      expect.objectContaining({
        userId: 'user002',
        approveId: 'OT20260310001-1',
        status: 'CANCELLED',
      }),
    ]);
    expect(attendanceService.approveCancel).toHaveBeenCalledWith('user002', 'OT20260310001-1');
  });

  it('未传时间范围时应自动限制为最近60天后再校验精确审批号', async () => {
    jest.useFakeTimers();
    try {
      jest.setSystemTime(new Date('2026-03-10T12:00:00+08:00'));

      const yidaService = {
        searchApprovedInstances: jest.fn().mockResolvedValue([]),
      };
      const attendanceService = {
        getApproveRecords: jest.fn().mockResolvedValue({ errcode: 0, result: { approve_list: [] } }),
        approveCancel: jest.fn(),
      };

      const service = new DingtalkRepairService(yidaService as any, attendanceService as any);
      const result = await service.cancelApprovals({
        taskCode: 'DINGTALK_FIELD_APPLICATION',
        userId: 'user003',
        approveId: 'FIELD20260310001-1',
        dryRun: true,
      });

      expect(result.success).toBe(true);
      expect(result.processedCount).toBe(0);
      expect(yidaService.searchApprovedInstances).toHaveBeenCalledWith(
        expect.any(String),
        '2026-01-10',
        '2026-03-10',
        'user003',
      );
    } finally {
      jest.useRealTimers();
    }
  });
});
