import type { ITeamRepository } from '../../domain/repositories/ITeamRepository';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { ITeamStatsRepository } from '../../domain/repositories/ITeamStatsRepository';
import type { IResultRepository } from '../../domain/repositories/IResultRepository';
import type { Logger } from '@core/shared/application';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
import { MediaReference } from '@core/domain/media/MediaReference';

export type GetAllTeamsInput = {};

export type GetAllTeamsErrorCode = 'REPOSITORY_ERROR';

export interface TeamSummary {
  id: string;
  name: string;
  tag: string;
  description: string;
  ownerId: string;
  leagues: string[];
  createdAt: Date;
  memberCount: number;
  totalWins?: number;
  totalRaces?: number;
  performanceLevel?: string;
  specialization?: string;
  region?: string;
  languages?: string[];
  logoRef?: MediaReference;
  logoUrl?: string | null;
  rating?: number;
  category?: string | undefined;
  isRecruiting: boolean;
}

export interface GetAllTeamsResult {
  teams: TeamSummary[];
  totalCount: number;
}

/**
 * Use Case for retrieving all teams.
 */
export class GetAllTeamsUseCase {
  constructor(
    private readonly teamRepository: ITeamRepository,
    private readonly teamMembershipRepository: ITeamMembershipRepository,
    private readonly teamStatsRepository: ITeamStatsRepository,
    private readonly resultRepository: IResultRepository,
    private readonly logger: Logger,
    private readonly output: UseCaseOutputPort<GetAllTeamsResult>,
  ) {}

  async execute(
    _input: GetAllTeamsInput = {},
  ): Promise<Result<void, ApplicationErrorCode<GetAllTeamsErrorCode, { message: string }>>> {
    void _input;
    this.logger.debug('Executing GetAllTeamsUseCase');

    try {
      const teams = await this.teamRepository.findAll();

      const enrichedTeams: TeamSummary[] = await Promise.all(
        teams.map(async (team) => {
          const memberCount = await this.teamMembershipRepository.countByTeamId(team.id);
          
          // Get logo reference from team entity
          const logoRef = team.logoRef;
          
          // Try to get pre-computed stats first
          let stats = await this.teamStatsRepository.getTeamStats(team.id);
          
          // If no pre-computed stats, compute them on-the-fly from results
          if (!stats) {
            this.logger.debug(`Computing stats for team ${team.id} on-the-fly`);
            const teamMemberships = await this.teamMembershipRepository.getTeamMembers(team.id);
            const teamMemberIds = teamMemberships.map(m => m.driverId.toString());
            
            const allResults = await this.resultRepository.findAll();
            const teamResults = allResults.filter(r => teamMemberIds.includes(r.driverId.toString()));
            
            const wins = teamResults.filter(r => r.position.toNumber() === 1).length;
            const totalRaces = teamResults.length;
            
            // Calculate rating
            const baseRating = 1000;
            const winBonus = wins * 50;
            const raceBonus = Math.min(totalRaces * 5, 200);
            const rating = Math.round(baseRating + winBonus + raceBonus);
            
            // Determine performance level
            let performanceLevel: 'beginner' | 'intermediate' | 'advanced' | 'pro';
            if (wins >= 20) performanceLevel = 'pro';
            else if (wins >= 10) performanceLevel = 'advanced';
            else if (wins >= 5) performanceLevel = 'intermediate';
            else performanceLevel = 'beginner';
            
            stats = {
              performanceLevel,
              specialization: 'mixed',
              region: 'International',
              languages: ['en'],
              totalWins: wins,
              totalRaces,
              rating,
            };
          }
          
          return {
            id: team.id,
            name: team.name.props,
            tag: team.tag.props,
            description: team.description.props,
            ownerId: team.ownerId.toString(),
            leagues: team.leagues.map(l => l.toString()),
            createdAt: team.createdAt.toDate(),
            memberCount,
            totalWins: stats!.totalWins,
            totalRaces: stats!.totalRaces,
            performanceLevel: stats!.performanceLevel,
            specialization: stats!.specialization,
            region: stats!.region,
            languages: stats!.languages,
            logoRef: logoRef,
            logoUrl: null, // Will be resolved by presenter
            rating: stats!.rating,
            category: team.category,
            isRecruiting: team.isRecruiting,
          };
        }),
      );

      const result: GetAllTeamsResult = {
        teams: enrichedTeams,
        totalCount: enrichedTeams.length,
      };

      this.logger.debug('Successfully retrieved all teams.');
      this.output.present(result);

      return Result.ok(undefined);
    } catch (error) {
      this.logger.error('Error retrieving all teams', error instanceof Error ? error : new Error(String(error)));
      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: { message: error instanceof Error ? error.message : 'Failed to load teams' },
      });
    }
  }
}