import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl'; import { Result } from '@/lib/contracts/Result'; import { DomainError, Service } from '@/lib/contracts/services/Service'; import { PenaltiesApiClient } from '@/lib/gateways/api/penalties/PenaltiesApiClient'; import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter'; import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger'; import type { PenaltyTypesReferenceDTO } from '@/lib/types/PenaltyTypesReferenceDTO'; import { injectable, unmanaged } from 'inversify'; /** * Penalty Service * * Orchestrates penalty operations by coordinating API calls and view model creation. * All dependencies are injected via constructor. */ @injectable() export class PenaltyService implements Service { private readonly apiClient: PenaltiesApiClient; constructor(@unmanaged() apiClient?: PenaltiesApiClient) { if (apiClient) { this.apiClient = apiClient; } else { const baseUrl = getWebsiteApiBaseUrl(); const logger = new ConsoleLogger(); const errorReporter = new EnhancedErrorReporter(logger); this.apiClient = new PenaltiesApiClient(baseUrl, errorReporter, logger); } } /** * Find penalties by race ID */ async findByRaceId(raceId: string): Promise { try { const res = await this.apiClient.getRacePenalties(raceId); const data = (res as any).value || res; return data.penalties; } catch (error: unknown) { throw error; } } /** * Get allowed penalty types and semantics */ async getPenaltyTypesReference(): Promise> { try { const data = await this.apiClient.getPenaltyTypesReference(); return Result.ok(data); } catch (error: unknown) { return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to get penalty types' }); } } /** * Apply a penalty */ async applyPenalty(input: unknown): Promise { try { // eslint-disable-next-line @typescript-eslint/no-explicit-any const res = await this.apiClient.applyPenalty(input as any); return (res as any)?.value || res; } catch (error: unknown) { throw error; } } }