import { describe, it, expect, vi, Mocked } from 'vitest';
import { LeagueSettingsService } from './LeagueSettingsService';
import { LeaguesApiClient } from '../../api/leagues/LeaguesApiClient';
import { DriversApiClient } from '../../api/drivers/DriversApiClient';
import { LeagueSettingsViewModel } from '@/lib/view-models/LeagueSettingsViewModel';

describe('LeagueSettingsService', () => {
  let mockLeaguesApiClient: Mocked<LeaguesApiClient>;
  let mockDriversApiClient: Mocked<DriversApiClient>;
  let service: LeagueSettingsService;

  beforeEach(() => {
    mockLeaguesApiClient = {
      getAllWithCapacity: vi.fn(),
      getLeagueConfig: vi.fn(),
      getScoringPresets: vi.fn(),
      getMemberships: vi.fn(),
      transferOwnership: vi.fn(),
    } as unknown as Mocked<LeaguesApiClient>;

    mockDriversApiClient = {
      getLeaderboard: vi.fn(),
      getDriver: vi.fn(),
    } as unknown as Mocked<DriversApiClient>;

    service = new LeagueSettingsService(mockLeaguesApiClient, mockDriversApiClient);
  });

  describe('getLeagueSettings', () => {
    it('should return league settings with all data', async () => {
      const leagueId = 'league-123';

      // Mock getAllWithCapacity
      mockLeaguesApiClient.getAllWithCapacity.mockResolvedValue({
        leagues: [
          { id: leagueId, name: 'Test League', ownerId: 'owner-123', capacity: 20, currentMembers: 10 },
        ],
      });

      // Mock getLeagueConfig
      mockLeaguesApiClient.getLeagueConfig.mockResolvedValue({
        config: { someConfig: 'value' },
      });

      // Mock getScoringPresets
      mockLeaguesApiClient.getScoringPresets.mockResolvedValue({
        presets: [{ id: 'preset-1', name: 'Preset 1' }],
      });

      // Mock getLeaderboard
      mockDriversApiClient.getLeaderboard.mockResolvedValue({
        drivers: [
          { id: 'owner-123', name: 'Owner Driver', rating: 1500, rank: 10 },
          { id: 'member-1', name: 'Member 1', rating: 1400, rank: 20 },
        ],
      });

      // Mock getDriver for owner
      mockDriversApiClient.getDriver.mockResolvedValue({
        id: 'owner-123',
        name: 'Owner Driver',
        avatarUrl: 'https://example.com/avatar.jpg',
        country: 'US',
      });

      // Mock getMemberships
      mockLeaguesApiClient.getMemberships.mockResolvedValue({
        members: [
          { driverId: 'member-1', role: 'member' },
        ],
      });

      const result = await service.getLeagueSettings(leagueId);

      expect(result).toBeInstanceOf(LeagueSettingsViewModel);
      expect(result.league.id).toBe(leagueId);
      expect(result.league.name).toBe('Test League');
      expect(result.league.ownerId).toBe('owner-123');
      expect(result.presets).toHaveLength(1);
      expect(result.owner).toBeDefined();
      expect(result.members).toHaveLength(1);
    });

    it('should return null when league not found', async () => {
      const leagueId = 'non-existent-league';

      mockLeaguesApiClient.getAllWithCapacity.mockResolvedValue({
        leagues: [],
      });

      const result = await service.getLeagueSettings(leagueId);

      expect(result).toBeNull();
    });

    it('should handle errors gracefully', async () => {
      const leagueId = 'league-123';

      mockLeaguesApiClient.getAllWithCapacity.mockRejectedValue(new Error('API error'));

      const result = await service.getLeagueSettings(leagueId);

      expect(result).toBeNull();
    });
  });

  describe('transferOwnership', () => {
    it('should call apiClient.transferOwnership and return success', async () => {
      const leagueId = 'league-123';
      const currentOwnerId = 'owner-123';
      const newOwnerId = 'new-owner-456';

      mockLeaguesApiClient.transferOwnership.mockResolvedValue({ success: true });

      const result = await service.transferOwnership(leagueId, currentOwnerId, newOwnerId);

      expect(mockLeaguesApiClient.transferOwnership).toHaveBeenCalledWith(leagueId, currentOwnerId, newOwnerId);
      expect(result).toBe(true);
    });

    it('should throw error when apiClient.transferOwnership fails', async () => {
      const leagueId = 'league-123';
      const currentOwnerId = 'owner-123';
      const newOwnerId = 'new-owner-456';

      const error = new Error('API call failed');
      mockLeaguesApiClient.transferOwnership.mockRejectedValue(error);

      await expect(service.transferOwnership(leagueId, currentOwnerId, newOwnerId)).rejects.toThrow('API call failed');
    });
  });
});