/**
 * Draft Eligibility Calculation for Omni Leagues
 *
 * Implements two key constraints:
 * 1. Team Flex Pick Limit: Teams can only use (totalRounds - totalSports) flex picks
 * 2. Global Sport Availability: Cannot draft from a sport if it prevents other teams
 *    from fulfilling their "at least one from each sport" requirement
 */

export interface SportAvailability {
  sportId: string;
  sportName: string;
  totalParticipants: number;
  draftedCount: number;
  undraftedCount: number;
  teamsStillNeeding: number;
  canDraftAsFirst: boolean;  // undraftedCount >= teamsStillNeeding
  canDraftAsFlex: boolean;    // undraftedCount > teamsStillNeeding
}

export interface DraftEligibility {
  teamId: string;
  eligibleSportIds: Set<string>;
  ineligibleReasons: Record<string, string>; // sportId -> reason
  flexPicksUsed: number;
  flexPicksAvailable: number;
  picksBySport: Record<string, number>;
  sportAvailability: Record<string, SportAvailability>;
}

interface PickData {
  teamId: string;
  participant: {
    id: string;
    sport: {
      id: string;
      name: string;
    };
  };
}

interface ParticipantData {
  id: string;
  sport: {
    id: string;
    name: string;
  };
}

interface SportData {
  id: string;
  name: string;
}

interface TeamData {
  id: string;
}

/**
 * Calculate which sports a team is eligible to draft from based on:
 * - Team's flex pick usage
 * - Global sport availability for all teams
 */
export function calculateDraftEligibility(
  teamId: string,
  teamPicks: PickData[],
  allPicks: PickData[],
  allParticipants: ParticipantData[],
  seasonSports: SportData[],
  totalRounds: number,
  allTeams: TeamData[]
): DraftEligibility {
  // Step 1: Calculate team's flex pick status
  const picksBySport: Record<string, number> = {};

  for (const pick of teamPicks) {
    const sportId = pick.participant.sport.id;
    picksBySport[sportId] = (picksBySport[sportId] || 0) + 1;
  }

  // Calculate flex picks used: sum of (picks - 1) for each sport with multiple picks
  let flexPicksUsed = 0;
  for (const sportId in picksBySport) {
    if (picksBySport[sportId] > 1) {
      flexPicksUsed += picksBySport[sportId] - 1;
    }
  }

  const totalSports = seasonSports.length;
  const flexPicksAvailable = totalRounds - totalSports;
  const hasFlexesRemaining = flexPicksUsed < flexPicksAvailable;

  // Step 2: Calculate global sport availability
  const sportAvailability: Record<string, SportAvailability> = {};

  for (const sport of seasonSports) {
    // Count total participants in this sport
    const totalParticipants = allParticipants.filter(
      p => p.sport.id === sport.id
    ).length;

    // Count drafted participants in this sport
    const draftedCount = allPicks.filter(
      pick => pick.participant.sport.id === sport.id
    ).length;

    const undraftedCount = totalParticipants - draftedCount;

    // Count teams that haven't drafted from this sport yet
    const teamsSportPicks: Record<string, number> = {};
    for (const pick of allPicks) {
      if (pick.participant.sport.id === sport.id) {
        teamsSportPicks[pick.teamId] = (teamsSportPicks[pick.teamId] || 0) + 1;
      }
    }

    const teamsStillNeeding = allTeams.filter(
      team => !teamsSportPicks[team.id] || teamsSportPicks[team.id] === 0
    ).length;

    sportAvailability[sport.id] = {
      sportId: sport.id,
      sportName: sport.name,
      totalParticipants,
      draftedCount,
      undraftedCount,
      teamsStillNeeding,
      canDraftAsFirst: undraftedCount >= teamsStillNeeding,
      canDraftAsFlex: undraftedCount > teamsStillNeeding,
    };
  }

  // Step 3: Combine constraints to determine eligibility
  const eligibleSportIds = new Set<string>();
  const ineligibleReasons: Record<string, string> = {};

  for (const sport of seasonSports) {
    const sportId = sport.id;
    const availability = sportAvailability[sportId];
    const currentTeamHasSport = (picksBySport[sportId] || 0) > 0;

    let isEligible = false;
    let reason = "";

    if (!currentTeamHasSport) {
      // Team hasn't drafted from this sport yet (would be first pick)
      if (availability.canDraftAsFirst) {
        isEligible = true;
      } else {
        reason = `Only ${availability.undraftedCount} participants left for ${availability.teamsStillNeeding} teams needing ${sport.name}`;
      }
    } else {
      // Team has drafted from this sport (would be flex pick)
      if (!hasFlexesRemaining) {
        reason = `All flex picks used (${flexPicksUsed}/${flexPicksAvailable})`;
      } else if (!availability.canDraftAsFlex) {
        reason = `Would prevent other teams from getting ${sport.name} (${availability.undraftedCount} left for ${availability.teamsStillNeeding} teams)`;
      } else {
        isEligible = true;
      }
    }

    if (isEligible) {
      eligibleSportIds.add(sportId);
    } else {
      ineligibleReasons[sportId] = reason;
    }
  }

  return {
    teamId,
    eligibleSportIds,
    ineligibleReasons,
    flexPicksUsed,
    flexPicksAvailable,
    picksBySport,
    sportAvailability,
  };
}

/**
 * Get a human-readable summary of draft eligibility status
 */
export function getEligibilitySummary(eligibility: DraftEligibility): string {
  const { flexPicksUsed, flexPicksAvailable, picksBySport, sportAvailability } = eligibility;

  const sportBreakdown = Object.entries(picksBySport)
    .map(([sportId, count]) => {
      const sport = sportAvailability[sportId];
      return `${sport?.sportName || sportId}: ${count}`;
    })
    .join(", ");

  return `Flex picks: ${flexPicksUsed}/${flexPicksAvailable} | Picks by sport: ${sportBreakdown || "None"}`;
}
