/**
 * Application Use Case: GetEntitySponsorshipPricingUseCase
 *
 * Retrieves sponsorship pricing configuration for any entity.
 * Used by sponsors to see available slots and prices.
 */

import type { ISponsorshipPricingRepository } from '../../domain/repositories/ISponsorshipPricingRepository';
import type { ISponsorshipRequestRepository } from '../../domain/repositories/ISponsorshipRequestRepository';
import type { ISeasonSponsorshipRepository } from '../../domain/repositories/ISeasonSponsorshipRepository';
import type { AsyncUseCase, Logger } from '@core/shared/application';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { GetEntitySponsorshipPricingDTO } from '../dto/GetEntitySponsorshipPricingDTO';
import type { GetEntitySponsorshipPricingResultDTO } from '../dto/GetEntitySponsorshipPricingResultDTO';

export class GetEntitySponsorshipPricingUseCase
  implements AsyncUseCase<GetEntitySponsorshipPricingDTO, GetEntitySponsorshipPricingResultDTO | null, 'REPOSITORY_ERROR'>
{
  constructor(
    private readonly sponsorshipPricingRepo: ISponsorshipPricingRepository,
    private readonly sponsorshipRequestRepo: ISponsorshipRequestRepository,
    private readonly seasonSponsorshipRepo: ISeasonSponsorshipRepository,
    private readonly logger: Logger,
  ) {}

  async execute(dto: GetEntitySponsorshipPricingDTO): Promise<Result<GetEntitySponsorshipPricingResultDTO | null, ApplicationErrorCode<'REPOSITORY_ERROR', { message: string }>>> {
    this.logger.debug(`Executing GetEntitySponsorshipPricingUseCase for entityType: ${dto.entityType}, entityId: ${dto.entityId}`);
    try {
      const pricing = await this.sponsorshipPricingRepo.findByEntity(dto.entityType, dto.entityId);

      if (!pricing) {
        this.logger.info(`No pricing found for entityType: ${dto.entityType}, entityId: ${dto.entityId}`);
        return Result.ok(null);
      }

      // Count pending requests by tier
      const pendingRequests = await this.sponsorshipRequestRepo.findPendingByEntity(
        dto.entityType,
        dto.entityId,
      );
      const pendingMainCount = pendingRequests.filter(r => r.tier === 'main').length;
      const pendingSecondaryCount = pendingRequests.filter(r => r.tier === 'secondary').length;

      // Count filled slots (for seasons, check SeasonSponsorship table)
      let filledMainSlots = 0;
      let filledSecondarySlots = 0;

      if (dto.entityType === 'season') {
        const sponsorships = await this.seasonSponsorshipRepo.findBySeasonId(dto.entityId);
        const activeSponsorships = sponsorships.filter(s => s.isActive());
        filledMainSlots = activeSponsorships.filter(s => s.tier === 'main').length;
        filledSecondarySlots = activeSponsorships.filter(s => s.tier === 'secondary').length;
      }

      const result: GetEntitySponsorshipPricingResultDTO = {
        entityType: dto.entityType,
        entityId: dto.entityId,
        acceptingApplications: pricing.acceptingApplications,
        ...(pricing.customRequirements !== undefined
          ? { customRequirements: pricing.customRequirements }
          : {}),
      };

      if (pricing.mainSlot) {
        const mainMaxSlots = pricing.mainSlot.maxSlots;
        result.mainSlot = {
          tier: 'main',
          price: pricing.mainSlot.price.amount,
          currency: pricing.mainSlot.price.currency,
          formattedPrice: pricing.mainSlot.price.format(),
          benefits: pricing.mainSlot.benefits,
          available: pricing.mainSlot.available && filledMainSlots < mainMaxSlots,
          maxSlots: mainMaxSlots,
          filledSlots: filledMainSlots,
          pendingRequests: pendingMainCount,
        };
      }

      if (pricing.secondarySlots) {
        const secondaryMaxSlots = pricing.secondarySlots.maxSlots;
        result.secondarySlot = {
          tier: 'secondary',
          price: pricing.secondarySlots.price.amount,
          currency: pricing.secondarySlots.price.currency,
          formattedPrice: pricing.secondarySlots.price.format(),
          benefits: pricing.secondarySlots.benefits,
          available:
            pricing.secondarySlots.available && filledSecondarySlots < secondaryMaxSlots,
          maxSlots: secondaryMaxSlots,
          filledSlots: filledSecondarySlots,
          pendingRequests: pendingSecondaryCount,
        };
      }

      this.logger.info(`Successfully retrieved sponsorship pricing for entityType: ${dto.entityType}, entityId: ${dto.entityId}`);
      return Result.ok(result);
    } catch (error) {
      this.logger.error('Error executing GetEntitySponsorshipPricingUseCase', error instanceof Error ? error : new Error(String(error)));
      return Result.err({ code: 'REPOSITORY_ERROR', details: { message: error instanceof Error ? error.message : 'Unknown error occurred' } });
    }
  }
}