/**
 * Application Use Case: TeamRatingFactoryUseCase
 * 
 * Factory use case for creating team rating events from race results.
 * This replaces direct team rating calculations with event-based approach.
 * Mirrors the user rating factory pattern.
 */

import { TeamRatingEvent } from '@core/racing/domain/entities/TeamRatingEvent';
import { TeamRatingDelta } from '@core/racing/domain/value-objects/TeamRatingDelta';
import { TeamRatingDimensionKey } from '@core/racing/domain/value-objects/TeamRatingDimensionKey';
import { TeamRatingEventId } from '@core/racing/domain/value-objects/TeamRatingEventId';
import type { Logger } from '@core/shared/domain/Logger';
import { TeamDrivingRatingEventFactory } from '../../domain/services/TeamDrivingRatingEventFactory';
import { TeamRaceResultsProvider } from '../ports/TeamRaceResultsProvider';

export interface TeamRatingFactoryInput {
  raceId: string;
}

export interface TeamRatingFactoryOutput {
  success: boolean;
  raceId: string;
  events: TeamRatingEvent[];
  errors: string[];
}

export class TeamRatingFactoryUseCase {
  constructor(
    private readonly teamRaceResultsProvider: TeamRaceResultsProvider,
    private readonly logger: Logger
  ) {
    this.logger.info('[TeamRatingFactoryUseCase] Initialized');
  }

  async execute(input: TeamRatingFactoryInput): Promise<TeamRatingFactoryOutput> {
    this.logger.debug(`[TeamRatingFactoryUseCase] Creating rating events for race ${input.raceId}`);

    try {
      // Load team race results
      const teamRaceResults = await this.teamRaceResultsProvider.getTeamRaceResults(input.raceId);
      
      if (!teamRaceResults) {
        return {
          success: false,
          raceId: input.raceId,
          events: [],
          errors: ['Team race results not found'],
        };
      }

      // Use factory to create events
      const eventsByTeam = TeamDrivingRatingEventFactory.createDrivingEventsFromRace(teamRaceResults);
      
      // Flatten events from all teams
      const allEvents: TeamRatingEvent[] = [];
      for (const [, events] of eventsByTeam) {
        allEvents.push(...events);
      }

      if (allEvents.length === 0) {
        this.logger.info(`[TeamRatingFactoryUseCase] No events generated for race ${input.raceId}`);
        return {
          success: true,
          raceId: input.raceId,
          events: [],
          errors: [],
        };
      }

      this.logger.info(`[TeamRatingFactoryUseCase] Generated ${allEvents.length} events for race ${input.raceId}`);

      return {
        success: true,
        raceId: input.raceId,
        events: allEvents,
        errors: [],
      };

    } catch (error) {
      const errorMsg = `Failed to create rating events: ${error instanceof Error ? error.message : 'Unknown error'}`;
      this.logger.error('[TeamRatingFactoryUseCase] Error:', error instanceof Error ? error : new Error(String(error)));
      
      return {
        success: false,
        raceId: input.raceId,
        events: [],
        errors: [errorMsg],
      };
    }
  }

  /**
   * Create team rating events manually (for testing or manual adjustments)
   */
  createManualEvents(
    teamId: string,
    dimension: string,
    delta: number,
    reason: string,
    sourceType: 'race' | 'penalty' | 'vote' | 'adminAction' | 'manualAdjustment',
    sourceId?: string
  ): TeamRatingEvent[] {
    const source = sourceId ? { type: sourceType, id: sourceId } : { type: sourceType };
    
    const event = TeamRatingEvent.create({
      id: TeamRatingEventId.generate(),
      teamId,
      dimension: TeamRatingDimensionKey.create(dimension),
      delta: TeamRatingDelta.create(delta),
      occurredAt: new Date(),
      createdAt: new Date(),
      source: source,
      reason: { code: reason },
      visibility: { public: true },
      version: 1,
    });

    return [event];
  }
}