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

import { StandingOrmEntity } from '../entities/StandingOrmEntity';
import { InvalidStandingSchemaError } from '../errors/InvalidStandingSchemaError';
import { TypeOrmPersistenceSchemaError } from '../errors/TypeOrmPersistenceSchemaError';
import { assertInteger, assertNonEmptyString } from '../schema/TypeOrmSchemaGuards';

export class StandingOrmMapper {
  toOrmEntity(domain: Standing): StandingOrmEntity {
    const entity = new StandingOrmEntity();
    entity.id = domain.id;
    entity.leagueId = domain.leagueId.toString();
    entity.driverId = domain.driverId.toString();
    entity.points = domain.points.toNumber();
    entity.wins = domain.wins;
    entity.position = domain.position.toNumber();
    entity.racesCompleted = domain.racesCompleted;
    return entity;
  }

  toDomain(entity: StandingOrmEntity): Standing {
    const entityName = 'Standing';

    try {
      assertNonEmptyString(entityName, 'id', entity.id);
      assertNonEmptyString(entityName, 'leagueId', entity.leagueId);
      assertNonEmptyString(entityName, 'driverId', entity.driverId);
      assertInteger(entityName, 'points', entity.points);
      assertInteger(entityName, 'wins', entity.wins);
      assertInteger(entityName, 'position', entity.position);
      assertInteger(entityName, 'racesCompleted', entity.racesCompleted);
    } catch (error) {
      if (error instanceof TypeOrmPersistenceSchemaError) {
        throw new InvalidStandingSchemaError({
          fieldName: error.fieldName,
          reason: error.reason,
          message: error.message,
        });
      }
      throw error;
    }

    try {
      return Standing.rehydrate({
        id: entity.id,
        leagueId: entity.leagueId,
        driverId: entity.driverId,
        points: entity.points,
        wins: entity.wins,
        position: entity.position,
        racesCompleted: entity.racesCompleted,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Invalid persisted Standing';
      throw new InvalidStandingSchemaError({
        fieldName: 'unknown',
        reason: 'invalid_shape',
        message,
      });
    }
  }
}