/**
 * Integration Test: Sponsor League Detail Use Case Orchestration
 *
 * Tests the orchestration logic of sponsor league detail-related Use Cases:
 * - GetEntitySponsorshipPricingUseCase: Retrieves sponsorship pricing for leagues
 * - Validates that Use Cases correctly interact with their Ports (Repositories)
 * - Uses In-Memory adapters for fast, deterministic testing
 *
 * Focus: Business logic orchestration, NOT UI rendering
 */

import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
import { InMemorySponsorshipPricingRepository } from '../../../adapters/racing/persistence/inmemory/InMemorySponsorshipPricingRepository';
import { GetEntitySponsorshipPricingUseCase } from '../../../core/racing/application/use-cases/GetEntitySponsorshipPricingUseCase';
import { Logger } from '../../../core/shared/domain/Logger';

describe('Sponsor League Detail Use Case Orchestration', () => {
  let sponsorshipPricingRepository: InMemorySponsorshipPricingRepository;
  let getEntitySponsorshipPricingUseCase: GetEntitySponsorshipPricingUseCase;
  let mockLogger: Logger;

  beforeAll(() => {
    mockLogger = {
      info: () => {},
      debug: () => {},
      warn: () => {},
      error: () => {},
    } as unknown as Logger;
    
    sponsorshipPricingRepository = new InMemorySponsorshipPricingRepository(mockLogger);
    getEntitySponsorshipPricingUseCase = new GetEntitySponsorshipPricingUseCase(
      sponsorshipPricingRepository,
      mockLogger,
    );
  });

  beforeEach(() => {
    sponsorshipPricingRepository.clear();
  });

  describe('GetEntitySponsorshipPricingUseCase - Success Path', () => {
    it('should retrieve sponsorship pricing for a league', async () => {
      // Given: A league exists with ID "league-123"
      const leagueId = 'league-123';
      
      // And: The league has sponsorship pricing configured
      const pricing = {
        entityType: 'league' as const,
        entityId: leagueId,
        acceptingApplications: true,
        mainSlot: {
          price: { amount: 10000, currency: 'USD' },
          benefits: ['Primary logo placement', 'League page header banner'],
        },
        secondarySlots: {
          price: { amount: 2000, currency: 'USD' },
          benefits: ['Secondary logo on liveries', 'League page sidebar placement'],
        },
      };
      await sponsorshipPricingRepository.create(pricing);

      // When: GetEntitySponsorshipPricingUseCase.execute() is called
      const result = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'league',
        entityId: leagueId,
      });

      // Then: The result should contain sponsorship pricing
      expect(result.isOk()).toBe(true);
      const pricingResult = result.unwrap();

      // And: The entity type should be correct
      expect(pricingResult.entityType).toBe('league');

      // And: The entity ID should be correct
      expect(pricingResult.entityId).toBe(leagueId);

      // And: The league should be accepting applications
      expect(pricingResult.acceptingApplications).toBe(true);

      // And: The tiers should contain main slot
      expect(pricingResult.tiers).toHaveLength(2);
      expect(pricingResult.tiers[0].name).toBe('main');
      expect(pricingResult.tiers[0].price.amount).toBe(10000);
      expect(pricingResult.tiers[0].price.currency).toBe('USD');
      expect(pricingResult.tiers[0].benefits).toContain('Primary logo placement');

      // And: The tiers should contain secondary slot
      expect(pricingResult.tiers[1].name).toBe('secondary');
      expect(pricingResult.tiers[1].price.amount).toBe(2000);
      expect(pricingResult.tiers[1].price.currency).toBe('USD');
      expect(pricingResult.tiers[1].benefits).toContain('Secondary logo on liveries');
    });

    it('should retrieve sponsorship pricing with only main slot', async () => {
      // Given: A league exists with ID "league-123"
      const leagueId = 'league-123';
      
      // And: The league has sponsorship pricing configured with only main slot
      const pricing = {
        entityType: 'league' as const,
        entityId: leagueId,
        acceptingApplications: true,
        mainSlot: {
          price: { amount: 10000, currency: 'USD' },
          benefits: ['Primary logo placement', 'League page header banner'],
        },
      };
      await sponsorshipPricingRepository.create(pricing);

      // When: GetEntitySponsorshipPricingUseCase.execute() is called
      const result = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'league',
        entityId: leagueId,
      });

      // Then: The result should contain sponsorship pricing
      expect(result.isOk()).toBe(true);
      const pricingResult = result.unwrap();

      // And: The tiers should contain only main slot
      expect(pricingResult.tiers).toHaveLength(1);
      expect(pricingResult.tiers[0].name).toBe('main');
      expect(pricingResult.tiers[0].price.amount).toBe(10000);
    });

    it('should retrieve sponsorship pricing with custom requirements', async () => {
      // Given: A league exists with ID "league-123"
      const leagueId = 'league-123';
      
      // And: The league has sponsorship pricing configured with custom requirements
      const pricing = {
        entityType: 'league' as const,
        entityId: leagueId,
        acceptingApplications: true,
        customRequirements: 'Must have racing experience',
        mainSlot: {
          price: { amount: 10000, currency: 'USD' },
          benefits: ['Primary logo placement'],
        },
      };
      await sponsorshipPricingRepository.create(pricing);

      // When: GetEntitySponsorshipPricingUseCase.execute() is called
      const result = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'league',
        entityId: leagueId,
      });

      // Then: The result should contain sponsorship pricing
      expect(result.isOk()).toBe(true);
      const pricingResult = result.unwrap();

      // And: The custom requirements should be included
      expect(pricingResult.customRequirements).toBe('Must have racing experience');
    });

    it('should retrieve sponsorship pricing with not accepting applications', async () => {
      // Given: A league exists with ID "league-123"
      const leagueId = 'league-123';
      
      // And: The league has sponsorship pricing configured but not accepting applications
      const pricing = {
        entityType: 'league' as const,
        entityId: leagueId,
        acceptingApplications: false,
        mainSlot: {
          price: { amount: 10000, currency: 'USD' },
          benefits: ['Primary logo placement'],
        },
      };
      await sponsorshipPricingRepository.create(pricing);

      // When: GetEntitySponsorshipPricingUseCase.execute() is called
      const result = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'league',
        entityId: leagueId,
      });

      // Then: The result should contain sponsorship pricing
      expect(result.isOk()).toBe(true);
      const pricingResult = result.unwrap();

      // And: The league should not be accepting applications
      expect(pricingResult.acceptingApplications).toBe(false);
    });
  });

  describe('GetEntitySponsorshipPricingUseCase - Error Handling', () => {
    it('should return error when pricing is not configured', async () => {
      // Given: A league exists with ID "league-123"
      const leagueId = 'league-123';
      
      // And: The league has no sponsorship pricing configured
      // When: GetEntitySponsorshipPricingUseCase.execute() is called
      const result = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'league',
        entityId: leagueId,
      });

      // Then: Should return an error
      expect(result.isErr()).toBe(true);
      const error = result.unwrapErr();
      expect(error.code).toBe('PRICING_NOT_CONFIGURED');
    });
  });

  describe('Sponsor League Detail Data Orchestration', () => {
    it('should correctly retrieve sponsorship pricing with all tiers', async () => {
      // Given: A league exists with ID "league-123"
      const leagueId = 'league-123';
      
      // And: The league has sponsorship pricing configured with both main and secondary slots
      const pricing = {
        entityType: 'league' as const,
        entityId: leagueId,
        acceptingApplications: true,
        customRequirements: 'Must have racing experience',
        mainSlot: {
          price: { amount: 10000, currency: 'USD' },
          benefits: [
            'Primary logo placement on all liveries',
            'League page header banner',
            'Race results page branding',
            'Social media feature posts',
            'Newsletter sponsor spot',
          ],
        },
        secondarySlots: {
          price: { amount: 2000, currency: 'USD' },
          benefits: [
            'Secondary logo on liveries',
            'League page sidebar placement',
            'Race results mention',
            'Social media mentions',
          ],
        },
      };
      await sponsorshipPricingRepository.create(pricing);

      // When: GetEntitySponsorshipPricingUseCase.execute() is called
      const result = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'league',
        entityId: leagueId,
      });

      // Then: The sponsorship pricing should be correctly retrieved
      expect(result.isOk()).toBe(true);
      const pricingResult = result.unwrap();

      // And: The entity type should be correct
      expect(pricingResult.entityType).toBe('league');

      // And: The entity ID should be correct
      expect(pricingResult.entityId).toBe(leagueId);

      // And: The league should be accepting applications
      expect(pricingResult.acceptingApplications).toBe(true);

      // And: The custom requirements should be included
      expect(pricingResult.customRequirements).toBe('Must have racing experience');

      // And: The tiers should contain both main and secondary slots
      expect(pricingResult.tiers).toHaveLength(2);

      // And: The main slot should have correct price and benefits
      expect(pricingResult.tiers[0].name).toBe('main');
      expect(pricingResult.tiers[0].price.amount).toBe(10000);
      expect(pricingResult.tiers[0].price.currency).toBe('USD');
      expect(pricingResult.tiers[0].benefits).toHaveLength(5);
      expect(pricingResult.tiers[0].benefits).toContain('Primary logo placement on all liveries');

      // And: The secondary slot should have correct price and benefits
      expect(pricingResult.tiers[1].name).toBe('secondary');
      expect(pricingResult.tiers[1].price.amount).toBe(2000);
      expect(pricingResult.tiers[1].price.currency).toBe('USD');
      expect(pricingResult.tiers[1].benefits).toHaveLength(4);
      expect(pricingResult.tiers[1].benefits).toContain('Secondary logo on liveries');
    });

    it('should correctly retrieve sponsorship pricing for different entity types', async () => {
      // Given: A league exists with ID "league-123"
      const leagueId = 'league-123';
      
      // And: The league has sponsorship pricing configured
      const leaguePricing = {
        entityType: 'league' as const,
        entityId: leagueId,
        acceptingApplications: true,
        mainSlot: {
          price: { amount: 10000, currency: 'USD' },
          benefits: ['Primary logo placement'],
        },
      };
      await sponsorshipPricingRepository.create(leaguePricing);

      // And: A team exists with ID "team-456"
      const teamId = 'team-456';
      
      // And: The team has sponsorship pricing configured
      const teamPricing = {
        entityType: 'team' as const,
        entityId: teamId,
        acceptingApplications: true,
        mainSlot: {
          price: { amount: 5000, currency: 'USD' },
          benefits: ['Team logo placement'],
        },
      };
      await sponsorshipPricingRepository.create(teamPricing);

      // When: GetEntitySponsorshipPricingUseCase.execute() is called for league
      const leagueResult = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'league',
        entityId: leagueId,
      });

      // Then: The league pricing should be retrieved
      expect(leagueResult.isOk()).toBe(true);
      const leaguePricingResult = leagueResult.unwrap();
      expect(leaguePricingResult.entityType).toBe('league');
      expect(leaguePricingResult.entityId).toBe(leagueId);
      expect(leaguePricingResult.tiers[0].price.amount).toBe(10000);

      // When: GetEntitySponsorshipPricingUseCase.execute() is called for team
      const teamResult = await getEntitySponsorshipPricingUseCase.execute({
        entityType: 'team',
        entityId: teamId,
      });

      // Then: The team pricing should be retrieved
      expect(teamResult.isOk()).toBe(true);
      const teamPricingResult = teamResult.unwrap();
      expect(teamPricingResult.entityType).toBe('team');
      expect(teamPricingResult.entityId).toBe(teamId);
      expect(teamPricingResult.tiers[0].price.amount).toBe(5000);
    });
  });
});
