/**
 * Tests unitaires pour JiraAnalyticsService
 */

/* eslint-disable @typescript-eslint/no-explicit-any */
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { JiraAnalyticsService } from '../analytics';
import { JiraService } from '../jira';
import { jiraAnalyticsCache } from '../analytics-cache';

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

// Mock de analytics-cache
vi.mock('../analytics-cache', () => ({
  jiraAnalyticsCache: {
    get: vi.fn(),
    set: vi.fn(),
  },
}));

describe('JiraAnalyticsService', () => {
  let service: JiraAnalyticsService;
  let mockJiraService: any;

  const mockConfig = {
    enabled: true,
    baseUrl: 'https://test.atlassian.net',
    email: 'test@example.com',
    apiToken: 'token123',
    projectKey: 'TEST',
  };

  beforeEach(() => {
    vi.clearAllMocks();

    mockJiraService = {
      searchIssues: vi.fn(),
      validateProject: vi.fn(),
    };

    vi.mocked(JiraService).mockImplementation(() => mockJiraService as any);
    vi.mocked(jiraAnalyticsCache.get).mockReturnValue(null);

    service = new JiraAnalyticsService(mockConfig);
  });

  describe('getAllProjectIssues', () => {
    it('devrait récupérer toutes les issues du projet', async () => {
      const mockIssues = [
        { key: 'TEST-1', title: 'Issue 1' },
        { key: 'TEST-2', title: 'Issue 2' },
      ];

      vi.mocked(mockJiraService.searchIssues).mockResolvedValue(mockIssues);

      const issues = await service.getAllProjectIssues();

      expect(issues).toEqual(mockIssues);
      expect(mockJiraService.searchIssues).toHaveBeenCalledWith(
        'project = "TEST" ORDER BY created DESC'
      );
    });

    it('devrait gérer les erreurs', async () => {
      vi.mocked(mockJiraService.searchIssues).mockRejectedValue(
        new Error('API Error')
      );

      await expect(service.getAllProjectIssues()).rejects.toThrow();
    });
  });

  describe('getProjectAnalytics', () => {
    it('devrait retourner les analytics depuis le cache si disponible', async () => {
      const cachedAnalytics = {
        project: { key: 'TEST', name: 'Test', totalIssues: 0 },
        teamMetrics: {
          totalAssignees: 0,
          activeAssignees: 0,
          issuesDistribution: [],
        },
        velocityMetrics: {
          currentSprintPoints: 0,
          sprintHistory: [],
          averageVelocity: 0,
        },
        cycleTimeMetrics: { averageCycleTime: 0, cycleTimeByType: [] },
        workInProgress: { byStatus: [], byAssignee: [] },
      };

      vi.mocked(jiraAnalyticsCache.get).mockReturnValue(cachedAnalytics as any);

      const analytics = await service.getProjectAnalytics();

      expect(analytics).toEqual(cachedAnalytics);
      expect(mockJiraService.searchIssues).not.toHaveBeenCalled();
    });

    it('devrait forcer le refresh si demandé', async () => {
      const cachedAnalytics = {
        project: { key: 'TEST', name: 'Test', totalIssues: 0 },
        teamMetrics: {
          totalAssignees: 0,
          activeAssignees: 0,
          issuesDistribution: [],
        },
        velocityMetrics: {
          currentSprintPoints: 0,
          sprintHistory: [],
          averageVelocity: 0,
        },
        cycleTimeMetrics: { averageCycleTime: 0, cycleTimeByType: [] },
        workInProgress: { byStatus: [], byAssignee: [] },
      };

      vi.mocked(jiraAnalyticsCache.get).mockReturnValue(cachedAnalytics as any);
      vi.mocked(mockJiraService.validateProject).mockResolvedValue({
        exists: true,
        name: 'Test Project',
      });
      vi.mocked(mockJiraService.searchIssues).mockResolvedValue([]);

      await service.getProjectAnalytics(true);

      expect(mockJiraService.searchIssues).toHaveBeenCalled();
    });
  });
});
