import { Result } from '@core/shared/domain/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
import type { SeasonSponsorshipRepository } from '../../domain/repositories/SeasonSponsorshipRepository';
export type GetSeasonSponsorshipsInput = {
  seasonId: string;
};

export type SeasonSponsorshipMetrics = {
  drivers: number;
  races: number;
  completedRaces: number;
  impressions: number;
};

export type SeasonSponsorshipFinancials = {
  amount: number;
  currency: string;
};

export type SeasonSponsorshipDetail = {
  id: string;
  leagueId: string;
  leagueName: string;
  seasonId: string;
  seasonName: string;
  seasonStartDate?: Date;
  seasonEndDate?: Date;
  tier: string;
  status: string;
  pricing: SeasonSponsorshipFinancials;
  platformFee: SeasonSponsorshipFinancials;
  netAmount: SeasonSponsorshipFinancials;
  metrics: SeasonSponsorshipMetrics;
  createdAt: Date;
  activatedAt?: Date;
};

export type GetSeasonSponsorshipsResult = {
  seasonId: string;
  sponsorships: SeasonSponsorshipDetail[];
};

export type GetSeasonSponsorshipsErrorCode =
  | 'SEASON_NOT_FOUND'
  | 'LEAGUE_NOT_FOUND'
  | 'REPOSITORY_ERROR';

export class GetSeasonSponsorshipsUseCase {
  constructor(private readonly seasonSponsorshipRepository: SeasonSponsorshipRepository,
    private readonly seasonRepository: SeasonRepository,
    private readonly leagueRepository: LeagueRepository,
    private readonly leagueMembershipRepository: LeagueMembershipRepository,
    private readonly raceRepository: RaceRepository) {}

  async execute(
    input: GetSeasonSponsorshipsInput,
  ): Promise<Result<GetSeasonSponsorshipsResult, ApplicationErrorCode<GetSeasonSponsorshipsErrorCode, { message: string }>>> {
    try {
      const { seasonId } = input;

      const season = await this.seasonRepository.findById(seasonId);
      if (!season) {
        return Result.err({
          code: 'SEASON_NOT_FOUND',
          details: {
            message: 'Season not found',
          },
        });
      }

      const league = await this.leagueRepository.findById(season.leagueId);
      if (!league) {
        return Result.err({
          code: 'LEAGUE_NOT_FOUND',
          details: {
            message: 'League not found for season',
          },
        });
      }

      const sponsorships = await this.seasonSponsorshipRepository.findBySeasonId(seasonId);

      // Pre-compute metrics shared across all sponsorships in this season
      const memberships = await this.leagueMembershipRepository.getLeagueMembers(season.leagueId);
      const driverCount = memberships.length;

      const races = await this.raceRepository.findByLeagueId(season.leagueId);
      const raceCount = races.length;
      const completedRaces = races.filter(r => r.status.isCompleted()).length;
      const impressions = completedRaces * driverCount * 100;

      const sponsorshipDetails: SeasonSponsorshipDetail[] = sponsorships.map((sponsorship) => {
        const platformFee = sponsorship.getPlatformFee();
        const netAmount = sponsorship.getNetAmount();

        const detail: SeasonSponsorshipDetail = {
          id: sponsorship.id,
          leagueId: league.id.toString(),
          leagueName: league.name.toString(),
          seasonId: season.id,
          seasonName: season.name,
          tier: sponsorship.tier.toString(),
          status: sponsorship.status.toString(),
          pricing: {
            amount: sponsorship.pricing.amount,
            currency: sponsorship.pricing.currency,
          },
          platformFee: {
            amount: platformFee.amount,
            currency: platformFee.currency,
          },
          netAmount: {
            amount: netAmount.amount,
            currency: netAmount.currency,
          },
          metrics: {
            drivers: driverCount,
            races: raceCount,
            completedRaces,
            impressions,
          },
          createdAt: sponsorship.createdAt,
          ...(season.startDate ? { seasonStartDate: season.startDate } : {}),
          ...(season.endDate ? { seasonEndDate: season.endDate } : {}),
          ...(sponsorship.activatedAt ? { activatedAt: sponsorship.activatedAt } : {}),
        };

        return detail;
      });

      const result: GetSeasonSponsorshipsResult = {
        seasonId,
        sponsorships: sponsorshipDetails,
      };

      return Result.ok(result);
    } catch (err) {
      const error = err as { message?: string } | undefined;

      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: {
          message: error?.message ?? 'Failed to fetch season sponsorships',
        },
      });
    }
  }
}
