import { vi, describe, it, expect, beforeEach } from 'vitest';
import { InMemoryLeagueScoringConfigRepository } from './InMemoryLeagueScoringConfigRepository';
import { LeagueScoringConfig, type LeagueScoringConfigProps } from '@core/racing/domain/entities/LeagueScoringConfig';
import type { ChampionshipConfig } from '@core/racing/domain/types/ChampionshipConfig';
import { PointsTable } from '@core/racing/domain/value-objects/PointsTable';
import type { Logger } from '@core/shared/application';

const mockPointsTable = new PointsTable({ 1: 25, 2: 18, 3: 15 });

const mockChampionshipConfig: ChampionshipConfig = {
  id: 'champ1',
  name: 'Championship 1',
  type: 'driver',
  sessionTypes: ['main'],
  pointsTableBySessionType: {
    practice: mockPointsTable,
    qualifying: mockPointsTable,
    q1: mockPointsTable,
    q2: mockPointsTable,
    q3: mockPointsTable,
    sprint: mockPointsTable,
    main: mockPointsTable,
    timeTrial: mockPointsTable,
  },
  dropScorePolicy: { strategy: 'none' },
};

describe('InMemoryLeagueScoringConfigRepository', () => {
  let repository: InMemoryLeagueScoringConfigRepository;
  let mockLogger: Logger;

  beforeEach(() => {
    mockLogger = {
      debug: vi.fn(),
      info: vi.fn(),
      warn: vi.fn(),
      error: vi.fn(),
    };
    repository = new InMemoryLeagueScoringConfigRepository(mockLogger);
  });

  const createTestConfig = (seasonId: string, id?: string): LeagueScoringConfig => {
    const props: LeagueScoringConfigProps = {
      seasonId,
      championships: [mockChampionshipConfig],
    };
    if (id) {
      props.id = id;
    }
    return LeagueScoringConfig.create(props);
  };

  describe('constructor', () => {
    it('should initialize with a logger', () => {
      expect(repository).toBeDefined();
      expect(mockLogger.info).toHaveBeenCalledWith('InMemoryLeagueScoringConfigRepository initialized.');
    });
  });

  describe('findBySeasonId', () => {
    it('should return null if config not found', async () => {
      const result = await repository.findBySeasonId('nonexistent');
      expect(result).toBeNull();
      expect(mockLogger.debug).toHaveBeenCalledWith('[InMemoryLeagueScoringConfigRepository] Finding config for season: nonexistent.');
      expect(mockLogger.warn).toHaveBeenCalledWith('No config found for season: nonexistent.');
    });

    it('should return the config if found', async () => {
      const config = createTestConfig('season1');
      await repository.save(config);

      const result = await repository.findBySeasonId('season1');
      expect(result).toEqual(config);
      expect(mockLogger.info).toHaveBeenCalledWith('Found config for season: season1.');
    });
  });

  describe('save', () => {
    it('should save a new config', async () => {
      const config = createTestConfig('season1');
      const result = await repository.save(config);
      expect(result).toEqual(config);
      expect(mockLogger.debug).toHaveBeenCalledWith('[InMemoryLeagueScoringConfigRepository] Saving config for season: season1.');
      expect(mockLogger.info).toHaveBeenCalledWith('Config for season season1 saved successfully.');
    });

    it('should update existing config', async () => {
      const config1 = createTestConfig('season1');
      await repository.save(config1);

      const config2 = createTestConfig('season1', 'updated-id');
      const result = await repository.save(config2);
      expect(result).toEqual(config2);

      const found = await repository.findBySeasonId('season1');
      expect(found).toEqual(config2);
    });
  });
});