/**
 * Value Object: SponsorshipPricing
 *
 * Represents the sponsorship slot configuration and pricing for any sponsorable entity.
 * Used by drivers, teams, races, and leagues to define their sponsorship offerings.
 */

import { Money } from './Money';
import type { IValueObject } from '@core/shared/domain';

export interface SponsorshipSlotConfig {
  tier: 'main' | 'secondary';
  price: Money;
  benefits: string[];
  available: boolean;
  maxSlots: number; // How many sponsors of this tier can exist (1 for main, 2 for secondary typically)
}

export interface SponsorshipPricingProps {
  mainSlot?: SponsorshipSlotConfig | undefined;
  secondarySlots?: SponsorshipSlotConfig | undefined;
  acceptingApplications: boolean;
  customRequirements?: string | undefined;
}

export class SponsorshipPricing implements IValueObject<SponsorshipPricingProps> {
  readonly mainSlot: SponsorshipSlotConfig | undefined;
  readonly secondarySlots: SponsorshipSlotConfig | undefined;
  readonly acceptingApplications: boolean;
  readonly customRequirements: string | undefined;

  private constructor(props: SponsorshipPricingProps) {
    this.mainSlot = props.mainSlot;
    this.secondarySlots = props.secondarySlots;
    this.acceptingApplications = props.acceptingApplications;
    this.customRequirements = props.customRequirements;
  }

  get props(): SponsorshipPricingProps {
    return {
      mainSlot: this.mainSlot,
      secondarySlots: this.secondarySlots,
      acceptingApplications: this.acceptingApplications,
      customRequirements: this.customRequirements,
    };
  }

  equals(other: IValueObject<SponsorshipPricingProps>): boolean {
    const a = this.props;
    const b = other.props;

    const mainEqual =
      (a.mainSlot === undefined && b.mainSlot === undefined) ||
      (a.mainSlot !== undefined &&
        b.mainSlot !== undefined &&
        a.mainSlot.tier === b.mainSlot.tier &&
        a.mainSlot.price.amount === b.mainSlot.price.amount &&
        a.mainSlot.price.currency === b.mainSlot.price.currency &&
        a.mainSlot.available === b.mainSlot.available &&
        a.mainSlot.maxSlots === b.mainSlot.maxSlots &&
        a.mainSlot.benefits.length === b.mainSlot.benefits.length &&
        a.mainSlot.benefits.every((val, idx) => val === b.mainSlot!.benefits[idx]));

    const secondaryEqual =
      (a.secondarySlots === undefined && b.secondarySlots === undefined) ||
      (a.secondarySlots !== undefined &&
        b.secondarySlots !== undefined &&
        a.secondarySlots.tier === b.secondarySlots.tier &&
        a.secondarySlots.price.amount === b.secondarySlots.price.amount &&
        a.secondarySlots.price.currency === b.secondarySlots.price.currency &&
        a.secondarySlots.available === b.secondarySlots.available &&
        a.secondarySlots.maxSlots === b.secondarySlots.maxSlots &&
        a.secondarySlots.benefits.length === b.secondarySlots.benefits.length &&
        a.secondarySlots.benefits.every(
          (val, idx) => val === b.secondarySlots!.benefits[idx],
        ));

    return (
      mainEqual &&
      secondaryEqual &&
      a.acceptingApplications === b.acceptingApplications &&
      a.customRequirements === b.customRequirements
    );
  }

  static create(props: Partial<SponsorshipPricingProps> = {}): SponsorshipPricing {
    return new SponsorshipPricing({
      ...(props.mainSlot !== undefined ? { mainSlot: props.mainSlot } : {}),
      ...(props.secondarySlots !== undefined ? { secondarySlots: props.secondarySlots } : {}),
      acceptingApplications: props.acceptingApplications ?? true,
      ...(props.customRequirements !== undefined ? { customRequirements: props.customRequirements } : {}),
    });
  }


  /**
   * Check if a specific tier is available
   */
  isSlotAvailable(tier: 'main' | 'secondary'): boolean {
    if (tier === 'main') {
      return !!this.mainSlot?.available;
    }
    return !!this.secondarySlots?.available;
  }

  /**
   * Get price for a specific tier
   */
  getPrice(tier: 'main' | 'secondary'): Money | null {
    if (tier === 'main') {
      return this.mainSlot?.price ?? null;
    }
    return this.secondarySlots?.price ?? null;
  }

  /**
   * Get benefits for a specific tier
   */
  getBenefits(tier: 'main' | 'secondary'): string[] {
    if (tier === 'main') {
      return this.mainSlot?.benefits ?? [];
    }
    return this.secondarySlots?.benefits ?? [];
  }

  /**
   * Update main slot pricing
   */
  updateMainSlot(config: Partial<SponsorshipSlotConfig>): SponsorshipPricing {
    const currentMain = this.mainSlot ?? {
      tier: 'main' as const,
      price: Money.create(0, 'USD'),
      benefits: [],
      available: true,
      maxSlots: 1,
    };

    const base = this.props;

    return new SponsorshipPricing({
      ...base,
      mainSlot: {
        ...currentMain,
        ...config,
        tier: 'main',
      },
    });
  }

  /**
   * Update secondary slot pricing
   */
  updateSecondarySlot(config: Partial<SponsorshipSlotConfig>): SponsorshipPricing {
    const currentSecondary = this.secondarySlots ?? {
      tier: 'secondary' as const,
      price: Money.create(0, 'USD'),
      benefits: [],
      available: true,
      maxSlots: 2,
    };

    const base = this.props;

    return new SponsorshipPricing({
      ...base,
      secondarySlots: {
        ...currentSecondary,
        ...config,
        tier: 'secondary',
      },
    });
  }

  /**
   * Enable/disable accepting applications
   */
  setAcceptingApplications(accepting: boolean): SponsorshipPricing {
    const base = this.props;

    return new SponsorshipPricing({
      ...base,
      acceptingApplications: accepting,
    });
  }
}