import PocketBase from "pocketbase";
import * as xlsx from "xlsx";
import { nanoid } from "nanoid";

import { createTeamsService } from "./src/lib/pocketbase/services/teams.ts";
import { createPlayersService } from "./src/lib/pocketbase/services/players.ts";
import { createMatchesService } from "./src/lib/pocketbase/services/matches.ts";
import { createTournamentsService } from "./src/lib/pocketbase/services/tournaments.ts";

const POCKETBASE_URL = "http://127.0.0.1:8090";
const EXCEL_FILE_PATH = "./Teams-2.xlsx";

const ADMIN_EMAIL = "kyle.yohler@gmail.com";
const ADMIN_PASSWORD = "xj44aqz9CWrNNM0o";

// --- Helpers ---
async function createPlayerIfMissing(playersService, nameColumn, idColumn) {
  const playerId = idColumn?.trim();
  if (playerId) return playerId;

  let firstName, lastName;
  if (!nameColumn || !nameColumn.trim()) {
    firstName = `Player_${nanoid(4)}`;
    lastName = "(Regional)";
  } else {
    const parts = nameColumn.trim().split(" ");
    firstName = parts[0];
    lastName = parts[1] || "(Regional)";
  }

  const newPlayer = await playersService.createPlayer({ first_name: firstName, last_name: lastName });
  return newPlayer.id;
}

async function handleTeamsSheet(rows, teamsService, playersService, pb, tournamentIdMap = {}) {
  console.log(`📥 Importing ${rows.length} teams...`);
  const teamIdMap = {}; // spreadsheet ID -> PocketBase ID

  for (const [i, row] of rows.entries()) {
    try {
      const spreadsheetTeamId = row["ID"]?.toString().trim();
      if (!spreadsheetTeamId) {
        console.warn(`⚠️ [${i + 1}] Team row missing spreadsheet ID, skipping.`);
        continue;
      }

      const p1Id = await createPlayerIfMissing(playersService, row["P1 Name"], row["P1 ID"]);
      const p2Id = await createPlayerIfMissing(playersService, row["P2 Name"], row["P2 ID"]);

      let name = row["Name"]?.trim();
      if (!name) {
        const p1First = row["P1 Name"]?.split(" ")[0] || "Player1";
        const p2First = row["P2 Name"]?.split(" ")[0] || "Player2";
        name = `${p1First} and ${p2First}`;
        console.warn(`⚠️ [${i + 1}] No team name found. Using generated name: ${name}`);
      }

      const existing = await pb.collection("teams").getFullList({
        filter: `name = "${name}"`,
        fields: "id",
      });

      if (existing.length > 0) {
        console.log(`ℹ️ [${i + 1}] Team "${name}" already exists, skipping.`);
        teamIdMap[spreadsheetTeamId] = existing[0].id;
        continue;
      }

      // If there's a tournament for this team, get its PB ID
      const tournamentSpreadsheetId = row["Tournament ID"]?.toString().trim();
      const tournamentId = tournamentSpreadsheetId ? tournamentIdMap[tournamentSpreadsheetId] : undefined;

      const teamInput = {
        name,
        primary_color: row.primary_color || "",
        accent_color: row.accent_color || "",
        logo: row.logo || "",
        players: [p1Id, p2Id],
        tournament: tournamentId, // single tournament relation,
        private: true
      };

      const team = await teamsService.createTeam(teamInput);
      teamIdMap[spreadsheetTeamId] = team.id;

      console.log(`✅ [${i + 1}] Created team: ${team.name} with players: ${[p1Id, p2Id].join(", ")}`);

      // Add the team to the tournament's "teams" relation
      if (tournamentId) {
        await pb.collection("tournaments").update(tournamentId, {
          "teams+": [team.id],
        });
        console.log(`✅ Added team "${team.name}" to tournament ${tournamentId}`);
      }
    } catch (err) {
      console.error(`❌ [${i + 1}] Failed to create team: ${err.message}`);
    }
  }

  return teamIdMap;
}


async function handleTournamentSheet(rows, tournamentsService, teamIdMap, pb) {
  console.log(`📥 Importing ${rows.length} tournaments...`);
  const tournamentIdMap = {};
  const validFormats = ["double_elim", "single_elim", "groups", "swiss", "swiss_bracket"];

  for (const [i, row] of rows.entries()) {
    try {
      const spreadsheetId = row["ID"]?.toString().trim();
      if (!spreadsheetId) {
        console.warn(`⚠️ [${i + 1}] Tournament missing spreadsheet ID, skipping.`);
        continue;
      }

      if (!row["Name"]) {
        console.warn(`⚠️ [${i + 1}] Tournament name missing, skipping.`);
        continue;
      }

      const format = validFormats.includes(row["Format"]) ? row["Format"] : "double_elim";

      // Convert start_time to ISO datetime string
      let startTime = null;
      if (row["Start Time"]) {
        try {
          startTime = new Date(row["Start Time"]).toISOString();
        } catch (e) {
          console.warn(`⚠️ [${i + 1}] Invalid start time format, using null`);
        }
      }

      const tournamentInput = {
        name: row["Name"],
        start_time: startTime,
        format,
        regional: true,
        teams: Object.values(teamIdMap), // Add all created teams
      };

      const tournament = await tournamentsService.createTournament(tournamentInput);
      tournamentIdMap[spreadsheetId] = tournament.id;

      console.log(`✅ [${i + 1}] Created tournament: ${tournament.name} with ${Object.values(teamIdMap).length} teams`);
    } catch (err) {
      console.error(`❌ [${i + 1}] Failed to create tournament: ${err.message}`);
    }
  }

  return tournamentIdMap;
}


async function handleMatchesSheet(rows, matchesService, teamIdMap, tournamentIdMap, pb) {
  console.log(`📥 Importing ${rows.length} matches...`);

  const tournamentMatchesMap = {};

  for (const [i, row] of rows.entries()) {
    try {
      const homeId = teamIdMap[row["Home ID"]];
      const awayId = teamIdMap[row["Away ID"]];
      const tournamentId = tournamentIdMap[row["Tournament ID"]];

      if (!homeId || !awayId || !tournamentId) {
        console.warn(`⚠️ [${i + 1}] Could not find mapping for Home, Away, or Tournament, skipping.`);
        continue;
      }

      // --- Ensure the teams are linked to the tournament ---
      for (const teamId of [homeId, awayId]) {
        const team = await pb.collection("teams").getOne(teamId, { fields: "tournaments" });
        const tournaments = team.tournaments || [];
        if (!tournaments.includes(tournamentId)) {
          // Add tournament to team
          await pb.collection("teams").update(teamId, { "tournaments+": [tournamentId] });
          // Add team to tournament
          await pb.collection("tournaments").update(tournamentId, { "teams+": [teamId] });
          console.log(`✅ Linked team ${team.name} to tournament ${tournamentId}`);
        }
      }

      // --- Create match ---
      const data = {
        tournament: tournamentId,
        home: homeId,
        away: awayId,
        home_cups: Number(row["Home cups"] || 0),
        away_cups: Number(row["Away cups"] || 0),
        status: "ended",
        lid: i+1
      };

      const match = await matchesService.createMatch(data);
      console.log(`✅ [${i + 1}] Created match ID: ${match.id}`);

      if (!tournamentMatchesMap[tournamentId]) tournamentMatchesMap[tournamentId] = [];
      tournamentMatchesMap[tournamentId].push(match.id);
    } catch (err) {
      console.error(`❌ [${i + 1}] Failed to create match: ${err.message}`);
    }
  }

  // Update each tournament with the created match IDs
  for (const [tournamentId, matchIds] of Object.entries(tournamentMatchesMap)) {
    try {
      await pb.collection("tournaments").update(tournamentId, { "matches+": matchIds });
      console.log(`✅ Updated tournament ${tournamentId} with ${matchIds.length} matches`);
    } catch (err) {
      console.error(`❌ Failed to update tournament ${tournamentId} with matches: ${err.message}`);
    }
  }
}


// --- Main Import ---
export async function importExcel() {
  const pb = new PocketBase(POCKETBASE_URL);
  await pb.admins.authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD);

  const teamsService = createTeamsService(pb);
  const playersService = createPlayersService(pb);
  const tournamentsService = createTournamentsService(pb);
  const matchesService = createMatchesService(pb);

  const workbook = xlsx.readFile(EXCEL_FILE_PATH);

  let teamIdMap  = {};
  let tournamentIdMap  = {};

  // Process sheets in correct order: Tournaments -> Teams -> Matches
  const sheetOrder = ["tournament", "tournaments", "teams", "matches"];
  const processedSheets = new Set();

  for (const sheetNamePattern of sheetOrder) {
    for (const sheetName of workbook.SheetNames) {
      if (processedSheets.has(sheetName)) continue;
      if (sheetName.toLowerCase() !== sheetNamePattern) continue;

      const worksheet = workbook.Sheets[sheetName];
      const rows = xlsx.utils.sheet_to_json(worksheet);

      console.log(`\n📘 Processing sheet: ${sheetName}`);

      switch (sheetName.toLowerCase()) {
        case "teams":
          teamIdMap = await handleTeamsSheet(rows, teamsService, playersService, pb, tournamentIdMap);
          break;
        case "tournament":
        case "tournaments":
          tournamentIdMap = await handleTournamentSheet(rows, tournamentsService, teamIdMap, pb);
          break;
        case "matches":
          await handleMatchesSheet(rows, matchesService, teamIdMap, tournamentIdMap, pb);
          break;
        default:
          console.log(`⚠️ No handler found for sheet '${sheetName}', skipping.`);
      }

      processedSheets.add(sheetName);
    }
  }

  console.log("\n🎉 All sheets imported successfully!");
}

// --- Run ---
importExcel().catch(console.error);