import type {
  Player,
  PlayerInfo,
  PlayerInput,
  PlayerUpdateInput,
  PlayerStats,
} from "@/features/players/types";
import type { Match } from "@/features/matches/types";
import { transformPlayer, transformPlayerInfo, transformMatch } from "@/lib/pocketbase/util/transform-types";
import PocketBase from "pocketbase";

export function createPlayersService(pb: PocketBase) {
  return {
    async getPlayerInfo(id: string): Promise<PlayerInfo> {
      const result = await pb.collection("players").getOne(id, {
        fields: "id,first_name,last_name"
      });
      return transformPlayerInfo(result);
    },

    async listPlayerInfos(): Promise<PlayerInfo[]> {
      const result = await pb.collection("players").getFullList({
        fields: "id,first_name,last_name",
      });
      return result.map(transformPlayerInfo);
    },
    async getPlayerByAuthId(authId: string): Promise<Player | null> {
      const result = await pb.collection("players").getList<Player>(1, 1, {
        filter: `auth_id = "${authId}"`,
        expand: 'teams'
      });
      return result.items[0] ? transformPlayer(result.items[0]) : null;
    },

    async getPlayer(id: string): Promise<Player> {
      const result = await pb.collection("players").getOne(id, {
        expand: "teams",
      });
      return transformPlayer(result);
    },

    async listPlayers(): Promise<Player[]> {
      const result = await pb.collection("players").getFullList<Player>({
        fields: "id,first_name,last_name",
      });
      return result.map(transformPlayer);
    },

    async createPlayer(data: PlayerInput): Promise<Player> {
      const result = await pb.collection("players").create<Player>(data);
      return transformPlayer(result);
    },

    async updatePlayer(id: string, data: PlayerUpdateInput): Promise<Player> {
      const result = await pb.collection("players").update<Player>(id, data);
      return transformPlayer(result);
    },

    async getUnassociatedPlayers(): Promise<Player[]> {
      const result = await pb.collection("players").getFullList<Player>({
        filter: 'auth_id = ""',
        fields: "id,first_name,last_name",
      });
      return result.map(transformPlayer);
    },

    async getPlayerStats(playerId: string, viewType: 'all' | 'mainline' | 'regional' = 'all'): Promise<PlayerStats> {
      try {
        const collectionMap = {
          all: 'player_stats',
          mainline: 'player_mainline_stats',
          regional: 'player_regional_stats',
        };

        const result = await pb.collection(collectionMap[viewType]).getFirstListItem<PlayerStats>(
          `player_id = "${playerId}"`
        );
        return result;
      } catch (error) {
        return {
          id: "",
          player_id: playerId,
          player_name: "",
          matches: 0,
          tournaments: 0,
          wins: 0,
          losses: 0,
          total_cups_made: 0,
          total_cups_against: 0,
          win_percentage: 0,
          avg_cups_per_match: 0,
          margin_of_victory: 0,
          margin_of_loss: 0,
        };
      }
    },

    async getAllPlayerStats(viewType: 'all' | 'mainline' | 'regional' = 'all'): Promise<PlayerStats[]> {
      const collectionMap = {
        all: 'player_stats',
        mainline: 'player_mainline_stats',
        regional: 'player_regional_stats',
      };

      const result = await pb.collection(collectionMap[viewType]).getFullList<PlayerStats>({
        sort: "-win_percentage,-total_cups_made",
      });
      return result;
    },

    async getPlayerMatches(playerId: string): Promise<Match[]> {
      const player = await pb.collection("players").getOne(playerId.trim(), {
        expand: "teams",
      });

      if (!player.expand?.teams || player.expand.teams.length === 0) {
        return [];
      }

      const teamIds = Array.isArray(player.expand.teams)
        ? player.expand.teams.map((team: any) => team.id)
        : [player.expand.teams.id];

      const teamFilter = teamIds.map(teamId => `home = "${teamId}" || away = "${teamId}"`).join(" || ");

      const result = await pb.collection("matches").getFullList({
        filter: `(${teamFilter}) && (status = "ended" || status = "started")`,
        sort: "-created",
        expand: "tournament,home,away,home.players,away.players",
      });

      return result.map((match) => transformMatch(match));
    },

    async getUnenrolledPlayers(tournamentId: string): Promise<Player[]> {
      try {
        const tournament = await pb.collection("tournaments").getOne(tournamentId, {
          fields: "teams",
          expand: "teams,teams.players"
        });

        const enrolledPlayerIds: string[] = [];
        if (tournament.expand?.teams) {
          const teams = Array.isArray(tournament.expand.teams) ? tournament.expand.teams : [tournament.expand.teams];
          teams.forEach((team: any) => {
            if (team.expand?.players) {
              const players = Array.isArray(team.expand.players) ? team.expand.players : [team.expand.players];
              players.forEach((player: any) => {
                enrolledPlayerIds.push(player.id);
              });
            }
          });
        }

        if (enrolledPlayerIds.length === 0) {
          const allPlayers = await pb.collection("players").getFullList<Player>({
            fields: "id,first_name,last_name,email",
          });
          return allPlayers.map(transformPlayer);
        }

        const filter = enrolledPlayerIds
          .map((playerId: string) => `id != "${playerId}"`)
          .join(" && ");

        const availablePlayers = await pb.collection("players").getFullList<Player>({
          filter,
          fields: "id,first_name,last_name,email",
        });

        return availablePlayers.map(transformPlayer);
      } catch (error) {
        console.error("Error getting unenrolled players:", error);
        const allPlayers = await pb.collection("players").getFullList<Player>({
          fields: "id,first_name,last_name,email",
        });
        return allPlayers.map(transformPlayer);
      }
    },

    async getPlayersActivity(): Promise<Player[]> {
      const result = await pb.collection("players").getFullList<Player>({
        sort: "-last_activity",
        fields: "id,first_name,last_name,auth_id,last_activity",
      });
      return result.map(transformPlayer);
    },
  };
}
