export type PlayerPropCandidateAuditIssueCode =
  | 'home_zero_candidates'
  | 'away_zero_candidates'
  | 'event_zero_candidates'
  | 'home_no_two_way_candidates'
  | 'away_no_two_way_candidates'
  | 'home_thin_surface'
  | 'away_thin_surface';

export interface PlayerPropCandidateAuditSideReport {
  teamName: string;
  teamShort: string;
  candidateCount: number;
  twoWayCandidateCount: number;
  oneWayCandidateCount: number;
  gapFilledCandidateCount: number;
  topStatTypes: Array<{ statType: string; count: number }>;
}

export interface PlayerPropCandidateAuditEventInput {
  league: string;
  eventId: string;
  matchup: string;
  startsAt: string;
  home: PlayerPropCandidateAuditSideReport;
  away: PlayerPropCandidateAuditSideReport;
}

export interface PlayerPropCandidateAuditEventReport extends PlayerPropCandidateAuditEventInput {
  issues: PlayerPropCandidateAuditIssueCode[];
}

export interface PlayerPropCandidateAuditLeagueSummary {
  league: string;
  events: number;
  teams: number;
  zeroCandidateTeams: number;
  noTwoWayTeams: number;
  thinTeams: number;
  twoWayCandidates: number;
  oneWayCandidates: number;
  avgCandidatesPerTeam: number;
}

export interface PlayerPropCandidateAuditSummary {
  events: number;
  teams: number;
  zeroCandidateTeams: number;
  zeroCandidateEvents: number;
  noTwoWayTeams: number;
  thinTeams: number;
  twoWayCandidates: number;
  oneWayCandidates: number;
  avgCandidatesPerTeam: number;
}

export interface PlayerPropCandidateAuditReport {
  auditedAt: string;
  summary: PlayerPropCandidateAuditSummary;
  leagues: PlayerPropCandidateAuditLeagueSummary[];
  issueEventCount: number;
  passed: boolean;
  events: PlayerPropCandidateAuditEventReport[];
}

function roundToSingleDecimal(value: number): number {
  return Math.round(value * 10) / 10;
}

function buildIssues(event: PlayerPropCandidateAuditEventInput): PlayerPropCandidateAuditIssueCode[] {
  const issues: PlayerPropCandidateAuditIssueCode[] = [];

  if (event.home.candidateCount === 0) issues.push('home_zero_candidates');
  if (event.away.candidateCount === 0) issues.push('away_zero_candidates');
  if (event.home.candidateCount === 0 && event.away.candidateCount === 0) issues.push('event_zero_candidates');
  if (event.home.candidateCount > 0 && event.home.twoWayCandidateCount === 0) issues.push('home_no_two_way_candidates');
  if (event.away.candidateCount > 0 && event.away.twoWayCandidateCount === 0) issues.push('away_no_two_way_candidates');
  if (event.home.candidateCount > 0 && event.home.candidateCount < 2) issues.push('home_thin_surface');
  if (event.away.candidateCount > 0 && event.away.candidateCount < 2) issues.push('away_thin_surface');

  return issues;
}

export function buildPlayerPropCandidateAuditReport(params: {
  auditedAt: string;
  events: PlayerPropCandidateAuditEventInput[];
}): PlayerPropCandidateAuditReport {
  const events = params.events.map((event) => ({
    ...event,
    issues: buildIssues(event),
  }));

  const leagueMap = new Map<string, PlayerPropCandidateAuditLeagueSummary>();
  let zeroCandidateTeams = 0;
  let zeroCandidateEvents = 0;
  let noTwoWayTeams = 0;
  let thinTeams = 0;
  let twoWayCandidates = 0;
  let oneWayCandidates = 0;
  let totalCandidates = 0;

  for (const event of events) {
    if (event.issues.includes('event_zero_candidates')) zeroCandidateEvents++;

    for (const side of [event.home, event.away]) {
      const leagueKey = String(event.league || '').toLowerCase();
      const leagueSummary = leagueMap.get(leagueKey) || {
        league: leagueKey,
        events: 0,
        teams: 0,
        zeroCandidateTeams: 0,
        noTwoWayTeams: 0,
        thinTeams: 0,
        twoWayCandidates: 0,
        oneWayCandidates: 0,
        avgCandidatesPerTeam: 0,
      };

      if (side === event.home) {
        leagueSummary.events += 1;
      }

      leagueSummary.teams += 1;
      leagueSummary.twoWayCandidates += side.twoWayCandidateCount;
      leagueSummary.oneWayCandidates += side.oneWayCandidateCount;

      if (side.candidateCount === 0) {
        leagueSummary.zeroCandidateTeams += 1;
        zeroCandidateTeams += 1;
      } else {
        if (side.twoWayCandidateCount === 0) {
          leagueSummary.noTwoWayTeams += 1;
          noTwoWayTeams += 1;
        }
        if (side.candidateCount < 2) {
          leagueSummary.thinTeams += 1;
          thinTeams += 1;
        }
      }

      twoWayCandidates += side.twoWayCandidateCount;
      oneWayCandidates += side.oneWayCandidateCount;
      totalCandidates += side.candidateCount;

      leagueMap.set(leagueKey, leagueSummary);
    }
  }

  const leagues = [...leagueMap.values()]
    .map((league) => ({
      ...league,
      avgCandidatesPerTeam: league.teams > 0
        ? roundToSingleDecimal((league.twoWayCandidates + league.oneWayCandidates) / league.teams)
        : 0,
    }))
    .sort((a, b) => {
      const zeroDelta = b.zeroCandidateTeams - a.zeroCandidateTeams;
      if (zeroDelta !== 0) return zeroDelta;
      return a.league.localeCompare(b.league);
    });

  return {
    auditedAt: params.auditedAt,
    summary: {
      events: events.length,
      teams: events.length * 2,
      zeroCandidateTeams,
      zeroCandidateEvents,
      noTwoWayTeams,
      thinTeams,
      twoWayCandidates,
      oneWayCandidates,
      avgCandidatesPerTeam: events.length > 0 ? roundToSingleDecimal(totalCandidates / (events.length * 2)) : 0,
    },
    leagues,
    issueEventCount: events.filter((event) => event.issues.length > 0).length,
    passed: zeroCandidateTeams === 0 && noTwoWayTeams === 0 && thinTeams === 0,
    events,
  };
}

export function renderPlayerPropCandidateAuditMarkdown(report: PlayerPropCandidateAuditReport): string {
  const lines: string[] = [];
  lines.push('# Player Prop Candidate Audit');
  lines.push('');
  lines.push(`Audited At: ${report.auditedAt}`);
  lines.push('');
  lines.push('## Summary');
  lines.push('');
  lines.push(`- Events: ${report.summary.events}`);
  lines.push(`- Teams: ${report.summary.teams}`);
  lines.push(`- Zero-candidate teams: ${report.summary.zeroCandidateTeams}`);
  lines.push(`- Zero-candidate events: ${report.summary.zeroCandidateEvents}`);
  lines.push(`- Teams with no two-way candidates: ${report.summary.noTwoWayTeams}`);
  lines.push(`- Thin teams: ${report.summary.thinTeams}`);
  lines.push(`- Avg candidates/team: ${report.summary.avgCandidatesPerTeam}`);
  lines.push(`- Two-way candidates: ${report.summary.twoWayCandidates}`);
  lines.push(`- One-way candidates: ${report.summary.oneWayCandidates}`);
  lines.push(`- Passed: ${report.passed ? 'yes' : 'no'}`);
  lines.push('');
  lines.push('## By League');
  lines.push('');

  for (const league of report.leagues) {
    lines.push(`### ${league.league.toUpperCase()}`);
    lines.push('');
    lines.push(`- Events: ${league.events}`);
    lines.push(`- Teams: ${league.teams}`);
    lines.push(`- Zero-candidate teams: ${league.zeroCandidateTeams}`);
    lines.push(`- Teams with no two-way candidates: ${league.noTwoWayTeams}`);
    lines.push(`- Thin teams: ${league.thinTeams}`);
    lines.push(`- Avg candidates/team: ${league.avgCandidatesPerTeam}`);
    lines.push(`- Two-way candidates: ${league.twoWayCandidates}`);
    lines.push(`- One-way candidates: ${league.oneWayCandidates}`);
    lines.push('');
  }

  const issueEvents = report.events.filter((event) => event.issues.length > 0);
  if (issueEvents.length > 0) {
    lines.push('## Events With Findings');
    lines.push('');
    for (const event of issueEvents) {
      lines.push(`### ${event.matchup} (${event.league.toUpperCase()})`);
      lines.push('');
      lines.push(`- Event ID: ${event.eventId}`);
      lines.push(`- Starts At: ${event.startsAt}`);
      lines.push(`- Issues: ${event.issues.join(', ')}`);
      lines.push(`- Home ${event.home.teamShort}: ${event.home.candidateCount} candidates`);
      lines.push(`- Away ${event.away.teamShort}: ${event.away.candidateCount} candidates`);
      lines.push('');
    }
  }

  return lines.join('\n').trim() + '\n';
}
