import { Money, type Currency, isCurrency } from '@core/racing/domain/value-objects/Money';

import { TypeOrmPersistenceSchemaError } from '../errors/TypeOrmPersistenceSchemaError';
import { assertNumber, assertRecord } from '../schema/TypeOrmSchemaGuards';

export type OrmMoney = { amount: number; currency: Currency };

export class MoneyOrmMapper {
  toOrm(money: Money): OrmMoney {
    return {
      amount: money.amount,
      currency: money.currency,
    };
  }

  toDomain(entityName: string, fieldName: string, value: unknown): Money {
    assertRecord(entityName, fieldName, value);

    const maybeAmount = (value as Record<string, unknown>).amount;
    const maybeCurrency = (value as Record<string, unknown>).currency;

    assertNumber(entityName, `${fieldName}.amount`, maybeAmount);

    if (typeof maybeCurrency !== 'string') {
      throw new TypeOrmPersistenceSchemaError({
        entityName,
        fieldName: `${fieldName}.currency`,
        reason: 'not_string',
      });
    }

    if (!isCurrency(maybeCurrency)) {
      throw new TypeOrmPersistenceSchemaError({
        entityName,
        fieldName: `${fieldName}.currency`,
        reason: 'invalid_enum_value',
      });
    }

    try {
      return Money.create(maybeAmount, maybeCurrency as Currency);
    } catch {
      throw new TypeOrmPersistenceSchemaError({ entityName, fieldName, reason: 'invalid_shape' });
    }
  }
}