/**
 * Tests unitaires pour JiraScheduler
 */

/* eslint-disable @typescript-eslint/no-explicit-any */
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { JiraScheduler } from '../scheduler';
import { userPreferencesService } from '@/services/core/user-preferences';
import { JiraService } from '../jira';
import { getToday, addMinutes } from '@/lib/date-utils';

// Mock de userPreferencesService
vi.mock('@/services/core/user-preferences', () => ({
  userPreferencesService: {
    getJiraConfig: vi.fn(),
    getJiraSchedulerConfig: vi.fn(),
  },
}));

// Mock de JiraService
vi.mock('../jira', () => ({
  JiraService: vi.fn(),
}));

// Mock de date-utils
vi.mock('@/lib/date-utils', () => ({
  getToday: vi.fn(),
  addMinutes: vi.fn(),
}));

describe('JiraScheduler', () => {
  let scheduler: JiraScheduler;
  let mockJiraService: any;

  beforeEach(() => {
    vi.clearAllMocks();
    scheduler = new JiraScheduler();
    vi.useFakeTimers();

    // Mock JiraService
    mockJiraService = {
      testConnection: vi.fn(),
      syncTasks: vi.fn(),
    };
    vi.mocked(JiraService).mockImplementation(() => mockJiraService as any);
  });

  afterEach(() => {
    scheduler.stop();
    vi.useRealTimers();
  });

  describe('start', () => {
    it('devrait démarrer le scheduler si activé et configuré', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);

      await scheduler.start('user1');

      expect(scheduler.isActive()).toBe(true);
    });

    it('ne devrait pas démarrer si désactivé', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: false,
        jiraSyncInterval: 'hourly',
      } as any);

      await scheduler.start('user1');

      expect(scheduler.isActive()).toBe(false);
    });

    it('ne devrait pas démarrer si Jira non configuré', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: false,
      } as any);

      await scheduler.start('user1');

      expect(scheduler.isActive()).toBe(false);
    });

    it('ne devrait pas démarrer deux fois', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);

      await scheduler.start('user1');
      const firstCall = scheduler.isActive();
      await scheduler.start('user1');
      const secondCall = scheduler.isActive();

      expect(firstCall).toBe(true);
      expect(secondCall).toBe(true);
    });
  });

  describe('stop', () => {
    it('devrait arrêter le scheduler', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);

      await scheduler.start('user1');
      expect(scheduler.isActive()).toBe(true);

      scheduler.stop();
      expect(scheduler.isActive()).toBe(false);
    });
  });

  describe('restart', () => {
    it('devrait redémarrer le scheduler', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);

      await scheduler.start('user1');
      expect(scheduler.isActive()).toBe(true);

      await scheduler.restart('user1');
      expect(scheduler.isActive()).toBe(true);
    });
  });

  describe('isActive', () => {
    it('devrait retourner false si pas démarré', () => {
      expect(scheduler.isActive()).toBe(false);
    });

    it('devrait retourner true si démarré', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);

      await scheduler.start('user1');
      expect(scheduler.isActive()).toBe(true);
    });
  });

  describe('performScheduledSync', () => {
    it('devrait exécuter une synchronisation automatique', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);
      vi.mocked(mockJiraService.testConnection).mockResolvedValue(true);
      vi.mocked(mockJiraService.syncTasks).mockResolvedValue({
        success: true,
        stats: {
          created: 5,
          updated: 3,
          skipped: 1,
        },
      } as any);

      await scheduler.start('user1');

      // Avancer le timer pour déclencher la synchronisation
      vi.advanceTimersByTime(60 * 60 * 1000); // 1 heure

      // Attendre que la synchronisation soit exécutée
      await vi.waitFor(() => {
        expect(mockJiraService.syncTasks).toHaveBeenCalled();
      });

      scheduler.stop();
    });

    it('devrait gérer les erreurs de connexion', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);
      vi.mocked(mockJiraService.testConnection).mockResolvedValue(false);

      await scheduler.start('user1');

      vi.advanceTimersByTime(60 * 60 * 1000);
      await vi.waitFor(() => {
        expect(mockJiraService.testConnection).toHaveBeenCalled();
      });

      scheduler.stop();
    });
  });

  describe('getNextSyncTime', () => {
    it('devrait retourner null si pas démarré', async () => {
      const nextTime = await scheduler.getNextSyncTime();

      expect(nextTime).toBeNull();
    });

    it('devrait calculer le prochain moment de synchronisation', async () => {
      const mockDate = new Date('2024-01-15T12:00:00Z');
      vi.mocked(getToday).mockReturnValue(mockDate);
      vi.mocked(addMinutes).mockReturnValue(new Date('2024-01-15T13:00:00Z'));

      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);

      await scheduler.start('user1');
      const nextTime = await scheduler.getNextSyncTime();

      expect(nextTime).not.toBeNull();
      expect(addMinutes).toHaveBeenCalled();
    });
  });

  describe('getStatus', () => {
    it('devrait retourner le statut du scheduler', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: true,
        jiraSyncInterval: 'daily',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: true,
        baseUrl: 'https://test.atlassian.net',
        email: 'test@example.com',
        apiToken: 'token123',
      } as any);

      await scheduler.start('user1');
      const status = await scheduler.getStatus('user1');

      expect(status.isRunning).toBe(true);
      expect(status.isEnabled).toBe(true);
      expect(status.interval).toBe('daily');
      expect(status.jiraConfigured).toBe(true);
    });

    it('devrait retourner le statut si pas démarré', async () => {
      vi.mocked(
        userPreferencesService.getJiraSchedulerConfig
      ).mockResolvedValue({
        jiraAutoSync: false,
        jiraSyncInterval: 'hourly',
      } as any);
      vi.mocked(userPreferencesService.getJiraConfig).mockResolvedValue({
        enabled: false,
      } as any);

      const status = await scheduler.getStatus('user1');

      expect(status.isRunning).toBe(false);
      expect(status.isEnabled).toBe(false);
    });
  });
});
