import { LeaguesApiClient } from "@/lib/api/leagues/LeaguesApiClient";
import { DriversApiClient } from "@/lib/api/drivers/DriversApiClient";
import { SponsorsApiClient } from "@/lib/api/sponsors/SponsorsApiClient";
import { RacesApiClient } from "@/lib/api/races/RacesApiClient";
import { CreateLeagueInputDTO } from "@/lib/types/generated/CreateLeagueInputDTO";
import { CreateLeagueOutputDTO } from "@/lib/types/generated/CreateLeagueOutputDTO";
import { CreateLeagueViewModel } from "@/lib/view-models/CreateLeagueViewModel";
import { LeagueAdminScheduleViewModel } from "@/lib/view-models/LeagueAdminScheduleViewModel";
import { LeagueMembershipsViewModel } from "@/lib/view-models/LeagueMembershipsViewModel";
import { LeagueScheduleViewModel, type LeagueScheduleRaceViewModel } from "@/lib/view-models/LeagueScheduleViewModel";
import { LeagueSeasonSummaryViewModel } from "@/lib/view-models/LeagueSeasonSummaryViewModel";
import { LeagueStandingsViewModel } from "@/lib/view-models/LeagueStandingsViewModel";
import { LeagueStatsViewModel } from "@/lib/view-models/LeagueStatsViewModel";
import { LeagueSummaryViewModel } from "@/lib/view-models/LeagueSummaryViewModel";
import { RemoveMemberViewModel } from "@/lib/view-models/RemoveMemberViewModel";
import { LeaguePageDetailViewModel } from "@/lib/view-models/LeaguePageDetailViewModel";
import { LeagueDetailPageViewModel, SponsorInfo } from "@/lib/view-models/LeagueDetailPageViewModel";
import { RaceViewModel } from "@/lib/view-models/RaceViewModel";
import type { LeagueAdminRosterJoinRequestViewModel } from "@/lib/view-models/LeagueAdminRosterJoinRequestViewModel";
import type { LeagueAdminRosterMemberViewModel } from "@/lib/view-models/LeagueAdminRosterMemberViewModel";
import type { MembershipRole } from "@/lib/types/MembershipRole";
import type { LeagueRosterJoinRequestDTO } from "@/lib/types/generated/LeagueRosterJoinRequestDTO";
import { SubmitBlocker, ThrottleBlocker } from "@/lib/blockers";
import type { RaceDTO } from "@/lib/types/generated/RaceDTO";
import { LeagueStatsDTO } from "@/lib/types/generated/LeagueStatsDTO";
import { LeagueScoringConfigDTO } from "@/lib/types/generated/LeagueScoringConfigDTO";
import type { LeagueMembership } from "@/lib/types/LeagueMembership";
import type { LeagueSeasonSummaryDTO } from '@/lib/types/generated/LeagueSeasonSummaryDTO';
import type { LeagueScheduleDTO } from '@/lib/types/generated/LeagueScheduleDTO';
import type { CreateLeagueScheduleRaceInputDTO } from '@/lib/types/generated/CreateLeagueScheduleRaceInputDTO';
import type { CreateLeagueScheduleRaceOutputDTO } from '@/lib/types/generated/CreateLeagueScheduleRaceOutputDTO';
import type { UpdateLeagueScheduleRaceInputDTO } from '@/lib/types/generated/UpdateLeagueScheduleRaceInputDTO';
import type { LeagueScheduleRaceMutationSuccessDTO } from '@/lib/types/generated/LeagueScheduleRaceMutationSuccessDTO';
import type { LeagueSeasonSchedulePublishOutputDTO } from '@/lib/types/generated/LeagueSeasonSchedulePublishOutputDTO';


/**
 * League Service
 *
 * Orchestrates league operations by coordinating API calls and view model creation.
 * All dependencies are injected via constructor.
 */
function parseIsoDate(value: string, fallback: Date): Date {
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) return fallback;
  return parsed;
}

function getBestEffortIsoDate(race: RaceDTO): string | undefined {
  const anyRace = race as unknown as { scheduledAt?: unknown; date?: unknown };

  if (typeof anyRace.scheduledAt === 'string') return anyRace.scheduledAt;
  if (typeof anyRace.date === 'string') return anyRace.date;

  return undefined;
}

function getOptionalStringField(race: RaceDTO, key: string): string | undefined {
  const anyRace = race as unknown as Record<string, unknown>;
  const value = anyRace[key];
  return typeof value === 'string' ? value : undefined;
}

function getOptionalBooleanField(race: RaceDTO, key: string): boolean | undefined {
  const anyRace = race as unknown as Record<string, unknown>;
  const value = anyRace[key];
  return typeof value === 'boolean' ? value : undefined;
}

function mapLeagueScheduleDtoToRaceViewModels(dto: LeagueScheduleDTO, now: Date = new Date()): LeagueScheduleRaceViewModel[] {
  return dto.races.map((race) => {
    const iso = getBestEffortIsoDate(race);
    const scheduledAt = iso ? parseIsoDate(iso, new Date(0)) : new Date(0);

    const isPast = scheduledAt.getTime() < now.getTime();
    const isUpcoming = !isPast;

    const status = getOptionalStringField(race, 'status') ?? (isPast ? 'completed' : 'scheduled');

    return {
      id: race.id,
      name: race.name,
      scheduledAt,
      isPast,
      isUpcoming,
      status,
      track: getOptionalStringField(race, 'track'),
      car: getOptionalStringField(race, 'car'),
      sessionType: getOptionalStringField(race, 'sessionType'),
      isRegistered: getOptionalBooleanField(race, 'isRegistered'),
    };
  });
}

export class LeagueService {
  private readonly submitBlocker = new SubmitBlocker();
  private readonly throttle = new ThrottleBlocker(500);

  constructor(
    private readonly apiClient: LeaguesApiClient,
    private readonly driversApiClient?: DriversApiClient,
    private readonly sponsorsApiClient?: SponsorsApiClient,
    private readonly racesApiClient?: RacesApiClient
  ) {}

  /**
   * Get all leagues with view model transformation
   */
  async getAllLeagues(): Promise<LeagueSummaryViewModel[]> {
    const dto = await this.apiClient.getAllWithCapacityAndScoring();
    const leagues = Array.isArray((dto as any)?.leagues) ? ((dto as any).leagues as any[]) : [];

    return leagues.map((league) => ({
      id: league.id,
      name: league.name,
      description: league.description,
      logoUrl: league.logoUrl ?? null, // Use API-provided logo URL
      ownerId: league.ownerId,
      createdAt: league.createdAt,
      maxDrivers: league.settings?.maxDrivers ?? 0,
      usedDriverSlots: league.usedSlots ?? 0,
      structureSummary: league.scoring?.scoringPresetName ?? 'Custom rules',
      scoringPatternSummary: league.scoring?.scoringPatternSummary,
      timingSummary: league.timingSummary ?? '',
      ...(league.category ? { category: league.category } : {}),
      ...(league.scoring ? { scoring: league.scoring } : {}),
    }));
  }

  /**
   * Get league standings with view model transformation
   */
  async getLeagueStandings(leagueId: string, currentUserId: string): Promise<LeagueStandingsViewModel> {
    // Core standings (positions, points, driverIds)
    const dto = await this.apiClient.getStandings(leagueId);
    const standings = ((dto as any)?.standings ?? []) as any[];

    // League memberships (roles, statuses)
    const membershipsDto = await this.apiClient.getMemberships(leagueId);
    const membershipEntries = ((membershipsDto as any)?.members ?? (membershipsDto as any)?.memberships ?? []) as any[];

    const memberships: LeagueMembership[] = membershipEntries.map((m) => ({
      driverId: m.driverId,
      leagueId,
      role: (m.role as LeagueMembership['role']) ?? 'member',
      joinedAt: m.joinedAt,
      status: 'active',
    }));

    // Resolve unique drivers that appear in standings
    const driverIds: string[] = Array.from(new Set(standings.map((entry: any) => entry.driverId)));
    const driverDtos = this.driversApiClient
      ? await Promise.all(driverIds.map((id: string) => this.driversApiClient!.getDriver(id)))
      : [];
    const drivers = driverDtos.filter((d): d is NonNullable<typeof d> => d !== null);

    const dtoWithExtras = { standings, drivers, memberships };

    return new LeagueStandingsViewModel(dtoWithExtras, currentUserId);
  }

  /**
   * Get league statistics
   */
  async getLeagueStats(): Promise<LeagueStatsViewModel> {
    const dto = await this.apiClient.getTotal();
    return new LeagueStatsViewModel(dto);
  }

  /**
   * Get league schedule
   *
   * Service boundary: returns ViewModels only (no DTOs / mappers in UI).
   */
  async getLeagueSchedule(leagueId: string): Promise<LeagueScheduleViewModel> {
    const dto = await this.apiClient.getSchedule(leagueId);
    const races = mapLeagueScheduleDtoToRaceViewModels(dto);
    return new LeagueScheduleViewModel(races);
  }

  /**
   * Admin schedule editor API (ViewModel boundary)
   */
  async getLeagueSeasonSummaries(leagueId: string): Promise<LeagueSeasonSummaryViewModel[]> {
    const dtos = await this.apiClient.getSeasons(leagueId);
    return dtos.map((dto) => new LeagueSeasonSummaryViewModel(dto));
  }

  async getAdminSchedule(leagueId: string, seasonId: string): Promise<LeagueAdminScheduleViewModel> {
    const dto = await this.apiClient.getSchedule(leagueId, seasonId);
    const races = mapLeagueScheduleDtoToRaceViewModels(dto);
    return new LeagueAdminScheduleViewModel({
      seasonId: dto.seasonId,
      published: dto.published,
      races,
    });
  }

  async publishAdminSchedule(leagueId: string, seasonId: string): Promise<LeagueAdminScheduleViewModel> {
    await this.apiClient.publishSeasonSchedule(leagueId, seasonId);
    return this.getAdminSchedule(leagueId, seasonId);
  }

  async unpublishAdminSchedule(leagueId: string, seasonId: string): Promise<LeagueAdminScheduleViewModel> {
    await this.apiClient.unpublishSeasonSchedule(leagueId, seasonId);
    return this.getAdminSchedule(leagueId, seasonId);
  }

  async createAdminScheduleRace(
    leagueId: string,
    seasonId: string,
    input: { track: string; car: string; scheduledAtIso: string },
  ): Promise<LeagueAdminScheduleViewModel> {
    const payload: CreateLeagueScheduleRaceInputDTO = { ...input, example: '' };
    await this.apiClient.createSeasonScheduleRace(leagueId, seasonId, payload);
    return this.getAdminSchedule(leagueId, seasonId);
  }

  async updateAdminScheduleRace(
    leagueId: string,
    seasonId: string,
    raceId: string,
    input: Partial<{ track: string; car: string; scheduledAtIso: string }>,
  ): Promise<LeagueAdminScheduleViewModel> {
    const payload: UpdateLeagueScheduleRaceInputDTO = { ...input, example: '' };
    await this.apiClient.updateSeasonScheduleRace(leagueId, seasonId, raceId, payload);
    return this.getAdminSchedule(leagueId, seasonId);
  }

  async deleteAdminScheduleRace(leagueId: string, seasonId: string, raceId: string): Promise<LeagueAdminScheduleViewModel> {
    await this.apiClient.deleteSeasonScheduleRace(leagueId, seasonId, raceId);
    return this.getAdminSchedule(leagueId, seasonId);
  }

  /**
   * Legacy DTO methods (kept for existing callers)
   */

  /**
   * Get league schedule DTO (season-scoped)
   *
   * Admin UI uses the raw DTO so it can render `published` and do CRUD refreshes.
   */
  async getLeagueScheduleDto(leagueId: string, seasonId: string): Promise<LeagueScheduleDTO> {
    return this.apiClient.getSchedule(leagueId, seasonId);
  }

  /**
   * Publish a league season schedule
   */
  async publishLeagueSeasonSchedule(leagueId: string, seasonId: string): Promise<LeagueSeasonSchedulePublishOutputDTO> {
    return this.apiClient.publishSeasonSchedule(leagueId, seasonId);
  }

  /**
   * Unpublish a league season schedule
   */
  async unpublishLeagueSeasonSchedule(leagueId: string, seasonId: string): Promise<LeagueSeasonSchedulePublishOutputDTO> {
    return this.apiClient.unpublishSeasonSchedule(leagueId, seasonId);
  }

  /**
   * Create a schedule race for a league season
   */
  async createLeagueSeasonScheduleRace(
    leagueId: string,
    seasonId: string,
    input: CreateLeagueScheduleRaceInputDTO,
  ): Promise<CreateLeagueScheduleRaceOutputDTO> {
    return this.apiClient.createSeasonScheduleRace(leagueId, seasonId, input);
  }

  /**
   * Update a schedule race for a league season
   */
  async updateLeagueSeasonScheduleRace(
    leagueId: string,
    seasonId: string,
    raceId: string,
    input: UpdateLeagueScheduleRaceInputDTO,
  ): Promise<LeagueScheduleRaceMutationSuccessDTO> {
    return this.apiClient.updateSeasonScheduleRace(leagueId, seasonId, raceId, input);
  }

  /**
   * Delete a schedule race for a league season
   */
  async deleteLeagueSeasonScheduleRace(
    leagueId: string,
    seasonId: string,
    raceId: string,
  ): Promise<LeagueScheduleRaceMutationSuccessDTO> {
    return this.apiClient.deleteSeasonScheduleRace(leagueId, seasonId, raceId);
  }

  /**
   * Get seasons for a league
   */
  async getLeagueSeasons(leagueId: string): Promise<LeagueSeasonSummaryDTO[]> {
    return this.apiClient.getSeasons(leagueId);
  }

  /**
   * Get league memberships
   */
  async getLeagueMemberships(leagueId: string, currentUserId: string): Promise<LeagueMembershipsViewModel> {
    const dto = await this.apiClient.getMemberships(leagueId);
    return new LeagueMembershipsViewModel(dto, currentUserId);
  }

  /**
   * Create a new league
   */
   async createLeague(input: CreateLeagueInputDTO): Promise<CreateLeagueOutputDTO> {
     if (!this.submitBlocker.canExecute() || !this.throttle.canExecute()) {
       return { success: false, leagueId: '' } as CreateLeagueOutputDTO;
     }

     this.submitBlocker.block();
     this.throttle.block();
     try {
       return await this.apiClient.create(input);
     } finally {
       this.submitBlocker.release();
     }
   }

  /**
   * Remove a member from league
   *
   * Overload:
   * - Legacy: removeMember(leagueId, performerDriverId, targetDriverId)
   * - Admin roster: removeMember(leagueId, targetDriverId) (actor derived from session)
   */
  async removeMember(leagueId: string, targetDriverId: string): Promise<{ success: boolean }>;
  async removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<RemoveMemberViewModel>;
  async removeMember(leagueId: string, arg1: string, arg2?: string): Promise<{ success: boolean } | RemoveMemberViewModel> {
    if (arg2 === undefined) {
      const dto = await this.apiClient.removeRosterMember(leagueId, arg1);
      return { success: dto.success };
    }

    const dto = await this.apiClient.removeMember(leagueId, arg1, arg2);
    return new RemoveMemberViewModel(dto as any);
  }

  /**
   * Update a member's role in league
   *
   * Overload:
   * - Legacy: updateMemberRole(leagueId, performerDriverId, targetDriverId, newRole)
   * - Admin roster: updateMemberRole(leagueId, targetDriverId, newRole) (actor derived from session)
   */
  async updateMemberRole(leagueId: string, targetDriverId: string, newRole: MembershipRole): Promise<{ success: boolean }>;
  async updateMemberRole(leagueId: string, performerDriverId: string, targetDriverId: string, newRole: string): Promise<{ success: boolean }>;
  async updateMemberRole(leagueId: string, arg1: string, arg2: string, arg3?: string): Promise<{ success: boolean }> {
    if (arg3 === undefined) {
      const dto = await this.apiClient.updateRosterMemberRole(leagueId, arg1, arg2);
      return { success: dto.success };
    }

    return this.apiClient.updateMemberRole(leagueId, arg1, arg2, arg3);
  }

  /**
   * Admin roster: members list as ViewModels
   */
  async getAdminRosterMembers(leagueId: string): Promise<LeagueAdminRosterMemberViewModel[]> {
    const dtos = await this.apiClient.getAdminRosterMembers(leagueId);
    return dtos.map((dto) => ({
      driverId: dto.driverId,
      driverName: dto.driver?.name ?? dto.driverId,
      role: (dto.role as MembershipRole) ?? 'member',
      joinedAtIso: dto.joinedAt,
    }));
  }

  /**
   * Admin roster: join requests list as ViewModels
   */
  async getAdminRosterJoinRequests(leagueId: string): Promise<LeagueAdminRosterJoinRequestViewModel[]> {
    const dtos = await this.apiClient.getAdminRosterJoinRequests(leagueId);
    return dtos.map((dto) => ({
      id: dto.id,
      leagueId: dto.leagueId,
      driverId: dto.driverId,
      driverName: this.resolveJoinRequestDriverName(dto),
      requestedAtIso: dto.requestedAt,
      message: dto.message,
    }));
  }

  async approveJoinRequest(leagueId: string, joinRequestId: string): Promise<{ success: boolean }> {
    const dto = await this.apiClient.approveRosterJoinRequest(leagueId, joinRequestId);
    return { success: dto.success };
  }

  async rejectJoinRequest(leagueId: string, joinRequestId: string): Promise<{ success: boolean }> {
    const dto = await this.apiClient.rejectRosterJoinRequest(leagueId, joinRequestId);
    return { success: dto.success };
  }

  private resolveJoinRequestDriverName(dto: LeagueRosterJoinRequestDTO): string {
    const driver = dto.driver as any;
    const name = driver && typeof driver === 'object' ? (driver.name as string | undefined) : undefined;
    return name ?? dto.driverId;
  }

  /**
   * Get league detail with owner, membership, and sponsor info
   */
  async getLeagueDetail(leagueId: string, currentDriverId: string): Promise<LeaguePageDetailViewModel | null> {
    if (!this.driversApiClient) return null;

    // For now, assume league data comes from getAllWithCapacity or a new endpoint
    // Since API may not have detailed league, we'll mock or assume
    // In real implementation, add getLeagueDetail to API
    const allLeagues = await this.apiClient.getAllWithCapacityAndScoring();
    const leagues = Array.isArray((allLeagues as any)?.leagues) ? ((allLeagues as any).leagues as any[]) : [];
    const leagueDto = leagues.find((l) => l?.id === leagueId);
    if (!leagueDto) return null;

    // LeagueWithCapacityDTO already carries core fields; fall back to placeholder description/owner when not provided
    const league = {
      id: leagueDto.id,
      name: leagueDto.name,
      description: leagueDto.description ?? 'Description not available',
      ownerId: leagueDto.ownerId ?? 'owner-id',
    };

    // Get owner
    const owner = await this.driversApiClient.getDriver(league.ownerId);
    const ownerName = owner ? (owner as any).name : `${league.ownerId.slice(0, 8)}...`;

    // Get membership
    const membershipsDto = await this.apiClient.getMemberships(leagueId);
    const members = Array.isArray((membershipsDto as any)?.members) ? ((membershipsDto as any).members as any[]) : [];
    const membership = members.find((m: any) => m?.driverId === currentDriverId);
    const isAdmin = membership ? ['admin', 'owner'].includes((membership as any).role) : false;

    // Get main sponsor
    let mainSponsor = null;
    if (this.sponsorsApiClient) {
      try {
        const seasons = await this.apiClient.getSeasons(leagueId);
        const seasonList = Array.isArray(seasons) ? (seasons as any[]) : [];
        const activeSeason = seasonList.find((s) => s?.status === 'active') ?? seasonList[0];
        if (activeSeason) {
          const sponsorshipsDto = await this.apiClient.getSeasonSponsorships(activeSeason.seasonId);
          const sponsorships = Array.isArray((sponsorshipsDto as any)?.sponsorships)
            ? ((sponsorshipsDto as any).sponsorships as any[])
            : [];
          const mainSponsorship = sponsorships.find((s: any) => s?.tier === 'main' && s?.status === 'active');
          if (mainSponsorship) {
            const sponsorId = (mainSponsorship as any).sponsorId ?? (mainSponsorship as any).sponsor?.id;
            if (sponsorId) {
              const sponsorResult = await this.sponsorsApiClient.getSponsor(sponsorId);
              const sponsor = (sponsorResult as any)?.sponsor ?? null;
              if (sponsor) {
                mainSponsor = {
                  name: sponsor.name,
                  logoUrl: sponsor.logoUrl ?? '',
                  websiteUrl: sponsor.websiteUrl ?? '',
                };
              }
            }
          }
        }
      } catch (error) {
        console.warn('Failed to load main sponsor:', error);
      }
    }

    return new LeaguePageDetailViewModel({
      league: {
        id: league.id,
        name: league.name,
        game: 'iRacing',
        tier: 'standard',
        season: 'Season 1',
        description: league.description,
        drivers: 0,
        races: 0,
        completedRaces: 0,
        totalImpressions: 0,
        avgViewsPerRace: 0,
        engagement: 0,
        rating: 0,
        seasonStatus: 'active',
        seasonDates: { start: new Date().toISOString(), end: new Date().toISOString() },
        sponsorSlots: {
          main: { available: true, price: 800, benefits: [] },
          secondary: { available: 2, total: 2, price: 250, benefits: [] }
        }
      },
      drivers: [],
      races: []
    });
  }

  /**
   * Get comprehensive league detail page data
   */
  async getLeagueDetailPageData(leagueId: string): Promise<LeagueDetailPageViewModel | null> {
    if (!this.driversApiClient || !this.sponsorsApiClient) return null;

    try {
      // Get league basic info
      const allLeagues = await this.apiClient.getAllWithCapacityAndScoring();
      const leagues = Array.isArray((allLeagues as any)?.leagues) ? ((allLeagues as any).leagues as any[]) : [];
      const league = leagues.find((l) => l?.id === leagueId);
      if (!league) return null;

      // Get owner
      const owner = await this.driversApiClient.getDriver(league.ownerId);

      // League scoring configuration is not exposed separately yet; use null to indicate "not configured" in the UI
      const scoringConfig: LeagueScoringConfigDTO | null = null;

      // Drivers list is limited to those present in memberships until a dedicated league-drivers endpoint exists
      const memberships = await this.apiClient.getMemberships(leagueId);
      const membershipMembers = Array.isArray((memberships as any)?.members) ? ((memberships as any).members as any[]) : [];
      const driverIds = membershipMembers.map((m: any) => m?.driverId).filter((id: any): id is string => typeof id === 'string');
      const driverDtos = await Promise.all(driverIds.map((id: string) => this.driversApiClient!.getDriver(id)));
      const drivers = driverDtos.filter((d: any): d is NonNullable<typeof d> => d !== null);

      // Get all races for this league via the leagues API helper
      // Service boundary hardening: tolerate `null/undefined` arrays from API.
      const leagueRaces = await this.apiClient.getRaces(leagueId);
      const allRaces = (leagueRaces.races ?? []).map((race) => new RaceViewModel(race));

      // League stats endpoint currently returns global league statistics rather than per-league values
      const leagueStats: LeagueStatsDTO = {
        totalMembers: league.usedSlots,
        totalRaces: allRaces.length,
        averageRating: 0,
      };

      // Get sponsors
      const sponsors = await this.getLeagueSponsors(leagueId);

      return new LeagueDetailPageViewModel(
        league,
        owner,
        scoringConfig,
        drivers,
        memberships,
        allRaces,
        leagueStats,
        sponsors
      );
    } catch (error) {
      console.error('Failed to load league detail page data:', error);
      return null;
    }
  }

  /**
   * Get sponsors for a league
   */
  private async getLeagueSponsors(leagueId: string): Promise<SponsorInfo[]> {
    if (!this.sponsorsApiClient) return [];

    try {
      const seasons = await this.apiClient.getSeasons(leagueId);
      const seasonList = Array.isArray(seasons) ? (seasons as any[]) : [];
      const activeSeason = seasonList.find((s) => s?.status === 'active') ?? seasonList[0];

      if (!activeSeason) return [];

      const sponsorships = await this.apiClient.getSeasonSponsorships(activeSeason.seasonId);
      const sponsorshipList = Array.isArray((sponsorships as any)?.sponsorships)
        ? ((sponsorships as any).sponsorships as any[])
        : [];
      const activeSponsorships = sponsorshipList.filter((s: any) => s?.status === 'active');

      const sponsorInfos: SponsorInfo[] = [];
      for (const sponsorship of activeSponsorships) {
        const sponsorResult = await this.sponsorsApiClient.getSponsor((sponsorship as any).sponsorId ?? (sponsorship as any).sponsor?.id);
        const sponsor = (sponsorResult as any)?.sponsor ?? null;
        if (sponsor) {
          // Tagline is not supplied by the sponsor API in this build; callers may derive one from marketing content if needed
          sponsorInfos.push({
            id: sponsor.id,
            name: sponsor.name,
            logoUrl: sponsor.logoUrl ?? '',
            websiteUrl: sponsor.websiteUrl ?? '',
            tier: ((sponsorship as any).tier as 'main' | 'secondary') ?? 'secondary',
            tagline: '',
          });
        }
      }

      // Sort: main sponsors first, then secondary
      sponsorInfos.sort((a, b) => {
        if (a.tier === 'main' && b.tier !== 'main') return -1;
        if (a.tier !== 'main' && b.tier === 'main') return 1;
        return 0;
      });

      return sponsorInfos;
    } catch (error) {
      console.warn('Failed to load sponsors:', error);
      return [];
    }
  }

  /**
   * Get league scoring presets
   */
  async getScoringPresets(): Promise<any[]> {
    const result = await this.apiClient.getScoringPresets();
    return result.presets;
  }
}