import { Injectable, Logger } from "@nestjs/common";
import { PrismaService } from "../../database/prisma.service";
import { Sport } from "@prisma/client";
import {
  countryFlagUrl,
  teamLogoUrl,
} from "../../common/utils/image-url.util";

@Injectable()
export class LeaguesService {
  private readonly logger = new Logger(LeaguesService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * Get all countries
   */
  async findAllCountries() {
    const countries = await this.prisma.country.findMany({
      orderBy: { name: "asc" },
    });
    return countries.map((c) => ({ ...c, flag: countryFlagUrl(c.id) }));
  }

  /**
   * Get country by ID
   */
  async findCountryById(id: string) {
    const country = await this.prisma.country.findUnique({
      where: { id },
      include: { leagues: true },
    });
    return country ? { ...country, flag: countryFlagUrl(country.id) } : null;
  }

  /**
   * Get all leagues
   */
  async findAllLeagues(sport?: Sport) {
    return this.prisma.league.findMany({
      where: sport ? { sport } : undefined,
      include: { country: true },
      orderBy: { name: "asc" },
    });
  }

  /**
   * Get league by ID
   */
  async findLeagueById(id: string) {
    return this.prisma.league.findUnique({
      where: { id },
      include: { country: true },
    });
  }

  /**
   * Get leagues by country
   */
  async findLeaguesByCountry(countryId: string, sport?: Sport) {
    return this.prisma.league.findMany({
      where: {
        countryId,
        ...(sport ? { sport } : {}),
      },
      include: { country: true },
      orderBy: { name: "asc" },
    });
  }

  /**
   * Get all teams
   */
  async findAllTeams(sport?: Sport, search?: string) {
    const teams = await this.prisma.team.findMany({
      where: {
        ...(sport ? { sport } : {}),
        ...(search ? { name: { contains: search, mode: "insensitive" } } : {}),
      },
      orderBy: { name: "asc" },
      take: 100,
    });
    return teams.map((t) => ({ ...t, logo: teamLogoUrl(t.id) }));
  }

  /**
   * Get team by ID
   */
  async findTeamById(id: string) {
    const team = await this.prisma.team.findUnique({
      where: { id },
    });
    return team ? { ...team, logo: teamLogoUrl(team.id) } : null;
  }

  /**
   * Search teams by name
   */
  async searchTeams(name: string, sport?: Sport) {
    const teams = await this.prisma.team.findMany({
      where: {
        name: { contains: name, mode: "insensitive" },
        ...(sport ? { sport } : {}),
      },
      take: 20,
    });
    return teams.map((t) => ({ ...t, logo: teamLogoUrl(t.id) }));
  }

  /**
   * Get team's matches (past + upcoming) with pagination
   */
  async getTeamRecentMatches(
    teamId: string,
    page: number = 1,
    limit: number = 20,
    season?: string,
  ) {
    const skip = (page - 1) * limit;
    const where: any = {
      OR: [{ homeTeamId: teamId }, { awayTeamId: teamId }],
    };

    if (season) {
      // season format expected: "2024-2025"
      const parts = season.split("-");
      if (parts.length === 2) {
        const startYear = parseInt(parts[0], 10);
        const endYear = parseInt(parts[1], 10);

        if (!isNaN(startYear) && !isNaN(endYear)) {
          // Season starts August 1st of startYear
          const startDate = new Date(Date.UTC(startYear, 7, 1)).getTime();
          // Season ends July 31st of endYear
          const endDate = new Date(
            Date.UTC(endYear, 6, 31, 23, 59, 59, 999),
          ).getTime();

          where.mstUtc = {
            gte: startDate,
            lte: endDate,
          };
        }
      }
    }

    const [data, total] = await this.prisma.$transaction([
      this.prisma.match.findMany({
        where,
        include: {
          homeTeam: true,
          awayTeam: true,
          league: { include: { country: true } },
        },
        orderBy: { mstUtc: "desc" },
        skip,
        take: limit,
      }),
      this.prisma.match.count({ where }),
    ]);

    return {
      data: data.map((m) => ({
        id: m.id,
        matchName: m.matchName,
        matchSlug: m.matchSlug,
        mstUtc: Number(m.mstUtc),
        scoreHome: m.scoreHome,
        scoreAway: m.scoreAway,
        status: m.status,
        state: m.state,
        homeTeamName: m.homeTeam?.name,
        homeTeamLogo: teamLogoUrl(m.homeTeamId) ?? null,
        awayTeamName: m.awayTeam?.name,
        awayTeamLogo: teamLogoUrl(m.awayTeamId) ?? null,
        leagueName: m.league?.name,
        countryName: m.league?.country?.name,
      })),
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * Get head-to-head matches between two teams
   */
  async getHeadToHead(teamId1: string, teamId2: string, limit: number = 10) {
    const matches = await this.prisma.match.findMany({
      where: {
        OR: [
          { homeTeamId: teamId1, awayTeamId: teamId2 },
          { homeTeamId: teamId2, awayTeamId: teamId1 },
        ],
        AND: [{ scoreHome: { not: null } }, { scoreAway: { not: null } }],
      },
      include: {
        homeTeam: true,
        awayTeam: true,
        league: true,
      },
      orderBy: { mstUtc: "desc" },
      take: limit,
    });

    // Calculate statistics
    let team1Wins = 0;
    let team2Wins = 0;
    let draws = 0;

    matches.forEach((match) => {
      const homeScore = Number(match.scoreHome ?? -1);
      const awayScore = Number(match.scoreAway ?? -1);

      // Skip matches without scores
      if (homeScore === -1 || awayScore === -1) return;

      const isTeam1Home = match.homeTeamId === teamId1;

      if (homeScore === awayScore) {
        draws++;
      } else if (
        (isTeam1Home && homeScore > awayScore) ||
        (!isTeam1Home && awayScore > homeScore)
      ) {
        team1Wins++;
      } else {
        team2Wins++;
      }
    });

    return {
      matches,
      team1Wins,
      team2Wins,
      draws,
    };
  }
}
