import { describe, expect, it, vi } from 'vitest';

import { Season } from '@core/racing/domain/entities/season/Season';

import { SeasonOrmEntity } from '../entities/SeasonOrmEntity';
import { TypeOrmPersistenceSchemaError } from '../errors/TypeOrmPersistenceSchemaError';
import { SeasonOrmMapper } from './SeasonOrmMapper';

describe('SeasonOrmMapper', () => {
  it('toDomain preserves persisted identity and uses rehydrate semantics (does not call create)', () => {
    const mapper = new SeasonOrmMapper();

    const entity = new SeasonOrmEntity();
    entity.id = '00000000-0000-4000-8000-000000000001';
    entity.leagueId = '00000000-0000-4000-8000-000000000002';
    entity.gameId = 'iracing';
    entity.name = 'Season 2025';
    entity.year = 2025;
    entity.order = 1;
    entity.status = 'planned';
    entity.startDate = null;
    entity.endDate = null;
    entity.schedule = null;
    entity.schedulePublished = false;
    entity.scoringConfig = null;
    entity.dropPolicy = null;
    entity.stewardingConfig = null;
    entity.maxDrivers = null;
    entity.participantCount = 3;

    if (typeof (Season as any).rehydrate !== 'function') {
      throw new Error('rehydrate-missing');
    }

    const rehydrateSpy = vi.spyOn(Season as any, 'rehydrate');
    const createSpy = vi.spyOn(Season, 'create').mockImplementation(() => {
      throw new Error('create-called');
    });

    const domain = mapper.toDomain(entity);

    expect(domain.id).toBe(entity.id);
    expect(createSpy).not.toHaveBeenCalled();
    expect(rehydrateSpy).toHaveBeenCalled();
  });

  it('toDomain validates persisted schedule schema and throws adapter-scoped base schema error type', () => {
    const mapper = new SeasonOrmMapper();

    const entity = new SeasonOrmEntity();
    entity.id = '00000000-0000-4000-8000-000000000001';
    entity.leagueId = '00000000-0000-4000-8000-000000000002';
    entity.gameId = 'iracing';
    entity.name = 'Season 2025';
    entity.year = null;
    entity.order = null;
    entity.status = 'planned';
    entity.startDate = null;
    entity.endDate = null;
    entity.schedule = 123 as unknown as never;
    entity.schedulePublished = false;
    entity.scoringConfig = null;
    entity.dropPolicy = null;
    entity.stewardingConfig = null;
    entity.maxDrivers = null;
    entity.participantCount = 0;

    try {
      mapper.toDomain(entity);
      throw new Error('expected-to-throw');
    } catch (error) {
      expect(error).toBeInstanceOf(TypeOrmPersistenceSchemaError);
      expect(error).toMatchObject({
        entityName: 'Season',
        fieldName: 'schedule',
        reason: 'not_object',
      });
    }
  });
});