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

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

import { LeagueOrmEntity } from '../entities/LeagueOrmEntity';
import { TypeOrmPersistenceSchemaError } from '../errors/TypeOrmPersistenceSchemaError';
import { LeagueOrmMapper } from './LeagueOrmMapper';

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

    const entity = new LeagueOrmEntity();
    entity.id = '00000000-0000-4000-8000-000000000001';
    entity.name = 'League Name';
    entity.description = 'League Description';
    entity.ownerId = '00000000-0000-4000-8000-000000000002';
    entity.settings = {
      pointsSystem: 'f1-2024',
      visibility: 'ranked',
      maxDrivers: 32,
      sessionDuration: 60,
      qualifyingFormat: 'open',
      stewarding: { decisionMode: 'admin_only' },
    };
    entity.createdAt = new Date('2025-01-01T00:00:00.000Z');
    entity.participantCount = 7;
    entity.discordUrl = null;
    entity.youtubeUrl = null;
    entity.websiteUrl = null;

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

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

    const domain = mapper.toDomain(entity);

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

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

    const entity = new LeagueOrmEntity();
    entity.id = '00000000-0000-4000-8000-000000000001';
    entity.name = 'League Name';
    entity.description = 'League Description';
    entity.ownerId = '00000000-0000-4000-8000-000000000002';
    entity.settings = 123 as unknown as never;
    entity.createdAt = new Date('2025-01-01T00:00:00.000Z');
    entity.participantCount = 0;
    entity.discordUrl = null;
    entity.youtubeUrl = null;
    entity.websiteUrl = null;

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