import { DingtalkSchedulerService } from '../../../../src/modules/organization/dingtalk/dingtalk-scheduler.service';

describe('DingtalkSchedulerService', () => {
  const prisma = {
    automationTask: {
      findFirst: jest.fn().mockResolvedValue({
        id: 'task-id',
        code: 'DINGTALK_FIELD_APPLICATION',
        status: 'DISABLED',
      }),
      update: jest.fn().mockResolvedValue({}),
    },
    automationExecution: {
      create: jest.fn().mockResolvedValue({
        id: 'execution-id',
        startedAt: new Date('2026-03-10T00:00:00+08:00'),
      }),
      update: jest.fn().mockResolvedValue({}),
    },
  };

  const authService = {
    getIsEnabled: jest.fn().mockResolvedValue(false),
  };

  const businessTripSync = { syncChanges: jest.fn() };
  const fieldApplicationSync = { sync: jest.fn().mockResolvedValue({ success: true, processedCount: 0, errors: [], duration: 1 }) };
  const overtimeSync = { sync: jest.fn() };
  const employeeInfoSync = { syncNewTable: jest.fn(), syncOldTable: jest.fn() };
  const annualLeaveSync = { sync: jest.fn() };
  const leaveExtensionSync = { sync: jest.fn() };
  const leaveReminderSync = { sync: jest.fn() };
  const employeeManagementService = { syncEmployeesFromDingtalk: jest.fn() };

  beforeEach(() => {
    jest.clearAllMocks();
    authService.getIsEnabled.mockResolvedValue(false);
    prisma.automationTask.findFirst.mockResolvedValue({
      id: 'task-id',
      code: 'DINGTALK_FIELD_APPLICATION',
      status: 'DISABLED',
    });
  });

  it('手动触发未传开始日期时应自动限制为最近60天', async () => {
    jest.useFakeTimers();
    try {
      jest.setSystemTime(new Date('2026-03-10T12:00:00+08:00'));
      const service = new DingtalkSchedulerService(
        prisma as any,
        authService as any,
        businessTripSync as any,
        fieldApplicationSync as any,
        overtimeSync as any,
        employeeInfoSync as any,
        annualLeaveSync as any,
        leaveExtensionSync as any,
        leaveReminderSync as any,
        employeeManagementService as any,
        {} as any,
        {} as any,
      );

      await service.triggerTask('DINGTALK_FIELD_APPLICATION');

      expect(fieldApplicationSync.sync).toHaveBeenCalledWith('2026-01-10', '2026-03-10', undefined, undefined);
    } finally {
      jest.useRealTimers();
    }
  });

  it('手动触发传入超过60天的开始日期时应自动收敛', async () => {
    jest.useFakeTimers();
    try {
      jest.setSystemTime(new Date('2026-03-10T12:00:00+08:00'));
      const logger = { log: jest.fn() };
      const service = new DingtalkSchedulerService(
        prisma as any,
        authService as any,
        businessTripSync as any,
        fieldApplicationSync as any,
        overtimeSync as any,
        employeeInfoSync as any,
        annualLeaveSync as any,
        leaveExtensionSync as any,
        leaveReminderSync as any,
        employeeManagementService as any,
        {} as any,
        {} as any,
      );

      await service.triggerTask('DINGTALK_FIELD_APPLICATION', '2025-12-01', '2026-03-10', undefined, undefined, logger as any);

      expect(fieldApplicationSync.sync).toHaveBeenCalledWith('2026-01-10', '2026-03-10', undefined, logger);
      expect(logger.log).toHaveBeenCalledWith('后端保护：开始日期早于最近 60 天，已自动收敛到 2026-01-10');
    } finally {
      jest.useRealTimers();
    }
  });

  it('定时外勤同步在 :15 应使用上一整段半小时窗口', async () => {
    jest.useFakeTimers();
    try {
      jest.setSystemTime(new Date('2026-03-10T08:15:00+08:00'));
      authService.getIsEnabled.mockResolvedValue(true);
      prisma.automationTask.findFirst.mockResolvedValue({
        id: 'task-id',
        code: 'DINGTALK_FIELD_APPLICATION',
        status: 'ACTIVE',
      });

      const service = new DingtalkSchedulerService(
        prisma as any,
        authService as any,
        businessTripSync as any,
        fieldApplicationSync as any,
        overtimeSync as any,
        employeeInfoSync as any,
        annualLeaveSync as any,
        leaveExtensionSync as any,
        leaveReminderSync as any,
        employeeManagementService as any,
        {} as any,
        {} as any,
      );

      await service.handleFieldApplicationSync();

      expect(fieldApplicationSync.sync).toHaveBeenCalledWith('2026-03-10 07:30:00', '2026-03-10 08:00:00');
    } finally {
      jest.useRealTimers();
    }
  });

  it('定时出差同步在 :45 应使用当前小时前半段窗口', async () => {
    jest.useFakeTimers();
    try {
      jest.setSystemTime(new Date('2026-03-10T08:45:00+08:00'));
      authService.getIsEnabled.mockResolvedValue(true);
      prisma.automationTask.findFirst.mockResolvedValue({
        id: 'task-id',
        code: 'DINGTALK_BUSINESS_TRIP',
        status: 'ACTIVE',
      });

      const service = new DingtalkSchedulerService(
        prisma as any,
        authService as any,
        businessTripSync as any,
        fieldApplicationSync as any,
        overtimeSync as any,
        employeeInfoSync as any,
        annualLeaveSync as any,
        leaveExtensionSync as any,
        leaveReminderSync as any,
        employeeManagementService as any,
        {} as any,
        {} as any,
      );

      await service.handleBusinessTripSync();

      expect(businessTripSync.syncChanges).toHaveBeenCalledWith('2026-03-10 08:00:00', '2026-03-10 08:30:00');
    } finally {
      jest.useRealTimers();
    }
  });
});
