import { Race } from '@core/racing/domain/entities/Race';
import { RaceStatus, type RaceStatusValue } from '@core/racing/domain/value-objects/RaceStatus';
import { SessionType, type SessionTypeValue } from '@core/racing/domain/value-objects/SessionType';

import { RaceOrmEntity } from '../entities/RaceOrmEntity';
import { assertEnumValue } from '../schema/TypeOrmSchemaGuards';

const VALID_SESSION_TYPES = [
  'practice',
  'qualifying',
  'q1',
  'q2',
  'q3',
  'sprint',
  'main',
  'timeTrial',
] as const satisfies readonly SessionTypeValue[];

const VALID_RACE_STATUSES = [
  'scheduled',
  'running',
  'completed',
  'cancelled',
] as const satisfies readonly RaceStatusValue[];

export class RaceOrmMapper {
  toOrmEntity(domain: Race): RaceOrmEntity {
    const entity = new RaceOrmEntity();
    entity.id = domain.id;
    entity.leagueId = domain.leagueId;
    entity.scheduledAt = domain.scheduledAt;
    entity.track = domain.track;
    entity.trackId = domain.trackId ?? null;
    entity.car = domain.car;
    entity.carId = domain.carId ?? null;
    entity.sessionType = domain.sessionType.props;
    entity.status = domain.status.toString();
    entity.strengthOfField = domain.getStrengthOfField() ?? null;
    entity.registeredCount = domain.registeredCountNumber ?? null;
    entity.maxParticipants = domain.getMaxParticipants() ?? null;
    return entity;
  }

  toDomain(entity: RaceOrmEntity): Race {
    const entityName = 'Race';

    assertEnumValue(entityName, 'sessionType', entity.sessionType, VALID_SESSION_TYPES);
    assertEnumValue(entityName, 'status', entity.status, VALID_RACE_STATUSES);

    const sessionType = new SessionType(entity.sessionType);
    const status = RaceStatus.create(entity.status);

    return Race.rehydrate({
      id: entity.id,
      leagueId: entity.leagueId,
      scheduledAt: entity.scheduledAt,
      track: entity.track,
      ...(entity.trackId !== null ? { trackId: entity.trackId } : {}),
      car: entity.car,
      ...(entity.carId !== null ? { carId: entity.carId } : {}),
      sessionType,
      status,
      ...(entity.strengthOfField !== null ? { strengthOfField: entity.strengthOfField } : {}),
      ...(entity.registeredCount !== null ? { registeredCount: entity.registeredCount } : {}),
      ...(entity.maxParticipants !== null ? { maxParticipants: entity.maxParticipants } : {}),
    });
  }
}