// =========================================================
// FILE: players.js | TYPE: Elite Player Management Logic
// =========================================================

import { db } from "./firebase-config.js";
import { requireAuth, setupLogoutButton } from "./app-guard.js";
import { showLoader, hideLoader } from "./loader.js";
import { showToast } from "./toast.js";

import {
  collection,
  addDoc,
  getDocs,
  serverTimestamp,
  query,
  orderBy,
  where,
  doc,
  getDoc,
  updateDoc,
  deleteDoc
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const playerForm = document.getElementById("playerForm");
const playerList = document.getElementById("playerList");
const teamCheckboxList = document.getElementById("teamCheckboxList");
const primaryTeamSelect = document.getElementById("primaryTeamId");
const playerTeamFilter = document.getElementById("playerTeamFilter");
const linkedUserId = document.getElementById("linkedUserId");

let activeProfile = null;
let teamsCache = [];
let playersCache = [];
let usersCache = [];
let editingPlayerId = null;

const submitButton = playerForm?.querySelector("button[type='submit']");

function setButtonLoading(isLoading, text = "Saving...") {
  if (!submitButton) return;

  submitButton.disabled = isLoading;
  submitButton.textContent = isLoading
    ? text
    : editingPlayerId
      ? "Update Player Profile"
      : "Save Player Profile";
}

function calculateAgeFromDob(dobValue) {
  if (!dobValue) return null;

  const dob = new Date(dobValue);
  const today = new Date();

  let age = today.getFullYear() - dob.getFullYear();
  const monthDiff = today.getMonth() - dob.getMonth();

  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < dob.getDate())) {
    age--;
  }

  return age;
}

function getTeamName(teamId) {
  const team = teamsCache.find((item) => item.id === teamId);

  return team
    ? team.name || team.teamName || team.title || "Unnamed Team"
    : "Unassigned";
}

function getPlayerName(player) {
  return `${player.firstName || ""} ${player.lastName || ""}`.trim() || "Unnamed Player";
}

function normalizePlayerName(value) {
  return String(value || "")
    .trim()
    .toLowerCase()
    .replace(/\s+/g, " ");
}

function playerAlreadyExistsInTeam(playerData) {
  const newFirstName = normalizePlayerName(playerData.firstName);
  const newLastName = normalizePlayerName(playerData.lastName);
  const newTeamIds = playerData.teamIds || [];

  return playersCache.some((player) => {
    if (editingPlayerId && player.id === editingPlayerId) return false;

    const existingTeamIds = player.teamIds || (player.teamId ? [player.teamId] : []);

    return (
      normalizePlayerName(player.firstName) === newFirstName &&
      normalizePlayerName(player.lastName) === newLastName &&
      existingTeamIds.some((teamId) => newTeamIds.includes(teamId))
    );
  });
}

function getInputValue(id) {
  return document.getElementById(id)?.value || "";
}

function getSelectedTeamIds() {
  return Array.from(
    document.querySelectorAll(".player-team-checkbox:checked")
  ).map((checkbox) => checkbox.value);
}

function getFormData() {
  const dob = getInputValue("dob");
  const teamIds = getSelectedTeamIds();
  const primaryTeamId = primaryTeamSelect?.value || teamIds[0] || "";

  return {
    firstName: getInputValue("firstName").trim(),
    lastName: getInputValue("lastName").trim(),
    dob,
    age: calculateAgeFromDob(dob),

    teamIds,
    primaryTeamId,
    teamId: primaryTeamId,
    teamName: getTeamName(primaryTeamId),
    teamNames: teamIds.map((teamId) => getTeamName(teamId)),

    ageGroup: getInputValue("ageGroup").trim(),
    position: getInputValue("position").trim(),
    jerseyNumber: getInputValue("jerseyNumber")
      ? Number(getInputValue("jerseyNumber"))
      : null,
    status: getInputValue("playerStatus") || "available",
    heightCm: getInputValue("heightCm")
      ? Number(getInputValue("heightCm"))
      : null,
    weightKg: getInputValue("weightKg")
      ? Number(getInputValue("weightKg"))
      : null,
    dominantSide: getInputValue("dominantSide"),
    guardianName: getInputValue("guardianName").trim(),
    guardianPhone: getInputValue("guardianPhone").trim(),
    guardianEmail: getInputValue("guardianEmail").trim(),
    emergencyContact: getInputValue("emergencyContact").trim(),
    emergencyPhone: getInputValue("emergencyPhone").trim(),
    medicalAid: getInputValue("medicalAid").trim(),
    allergies: getInputValue("allergies").trim(),
    medicalNotes: getInputValue("medicalNotes").trim(),
    userId: linkedUserId ? linkedUserId.value : ""
  };
}

function setFieldValue(id, value) {
  const field = document.getElementById(id);
  if (!field) return;

  field.value = value || "";
}

function populateForm(player) {
  editingPlayerId = player.id;

  if (linkedUserId) {
    linkedUserId.value = player.userId || "";
  }

  setFieldValue("firstName", player.firstName);
  setFieldValue("lastName", player.lastName);
  setFieldValue("dob", player.dob);
  const selectedTeamIds = player.teamIds || (player.teamId ? [player.teamId] : []);

  document.querySelectorAll(".player-team-checkbox").forEach((checkbox) => {
    checkbox.checked = selectedTeamIds.includes(checkbox.value);
  });

  if (primaryTeamSelect) {
    primaryTeamSelect.value = player.primaryTeamId || player.teamId || selectedTeamIds[0] || "";
  }
  setFieldValue("ageGroup", player.ageGroup);

  const positionSelect = document.getElementById("position");
  const savedPosition = player.position || "";

  if (positionSelect) {
    const matchingPosition = Array.from(positionSelect.options).some((option) => {
      return option.value === savedPosition;
    });

    positionSelect.value = matchingPosition ? savedPosition : "";
  }

  setFieldValue("jerseyNumber", player.jerseyNumber);
  setFieldValue("playerStatus", player.status || "available");
  setFieldValue("heightCm", player.heightCm);
  setFieldValue("weightKg", player.weightKg);
  setFieldValue("dominantSide", player.dominantSide);
  setFieldValue("guardianName", player.guardianName);
  setFieldValue("guardianPhone", player.guardianPhone);
  setFieldValue("guardianEmail", player.guardianEmail);
  setFieldValue("emergencyContact", player.emergencyContact);
  setFieldValue("emergencyPhone", player.emergencyPhone);
  setFieldValue("medicalAid", player.medicalAid);
  setFieldValue("allergies", player.allergies);
  setFieldValue("medicalNotes", player.medicalNotes);

  if (submitButton) {
    submitButton.textContent = "Update Player Profile";
  }

  window.scrollTo({ top: 0, behavior: "smooth" });
}

function resetFormMode() {
  editingPlayerId = null;

  if (playerForm) {
    playerForm.reset();
  }
  
  document.querySelectorAll(".player-team-checkbox").forEach((checkbox) => {
    checkbox.checked = false;
  });

  if (primaryTeamSelect) {
    primaryTeamSelect.value = "";
  }

  if (linkedUserId) {
    linkedUserId.value = "";
  }

  if (submitButton) {
    submitButton.textContent = "Save Player Profile";
    submitButton.disabled = false;
  }
}

function canAccessPlayer(player) {
  if (!activeProfile || !player) return false;

  const role = activeProfile.role;
  const assignedTeamIds = activeProfile.assignedTeamIds || [];
  const assignedPlayerIds = activeProfile.assignedPlayerIds || [];
  const playerTeamIds = player.teamIds || (player.teamId ? [player.teamId] : []);

  if (role === "director") return true;

  if (role === "coach") {
    return playerTeamIds.some((teamId) => assignedTeamIds.includes(teamId));
  }

  if (role === "biokineticist") {
    return (
      playerTeamIds.some((teamId) => assignedTeamIds.includes(teamId)) ||
      assignedPlayerIds.includes(player.id)
    );
  }

  if (role === "player") {
    return player.userId === activeProfile.uid || player.id === activeProfile.playerId;
  }

  return false;
}

function canAccessTeam(teamId, teamRecord = null) {
  if (!activeProfile) return false;

  const role = activeProfile.role;
  const assignedTeamIds = activeProfile.assignedTeamIds || [];

  if (role === "director") return true;

  if (role === "coach" || role === "biokineticist") {
    const assignedOnUserProfile = assignedTeamIds.includes(teamId);

    const assignedOnTeamRecord =
      teamRecord &&
      Array.isArray(teamRecord.assignedCoachIds) &&
      teamRecord.assignedCoachIds.includes(activeProfile.uid);

    return assignedOnUserProfile || assignedOnTeamRecord;
  }

  return false;
}

async function loadPageData() {
  if (!activeProfile?.organisationId) {
    throw new Error("No organisation linked to this user.");
  }
  
  const teamsQuery = query(
    collection(db, "teams"),
    where("organisationId", "==", activeProfile.organisationId),
    orderBy("createdAt", "desc")
  );

  const playersQuery = query(
    collection(db, "players"),
    where("organisationId", "==", activeProfile.organisationId),
    orderBy("createdAt", "desc")
  );

  const promises = [
    getDocs(teamsQuery),
    getDocs(playersQuery)
  ];

  if (linkedUserId && activeProfile.role === "director") {
    const usersQuery = query(
      collection(db, "users"),
      where("organisationId", "==", activeProfile.organisationId),
      where("role", "==", "player")
    );

    promises.push(getDocs(usersQuery));
  }

  const [teamsSnapshot, playersSnapshot, usersSnapshot] = await Promise.all(promises);

  teamsCache = teamsSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((team) => canAccessTeam(team.id, team));

  playersCache = playersSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((player) => canAccessPlayer(player));

  usersCache = usersSnapshot
    ? usersSnapshot.docs.map((docSnap) => ({
        id: docSnap.id,
        ...docSnap.data()
      }))
    : [];
}

function renderTeamDropdowns() {
  if (!teamCheckboxList || !primaryTeamSelect || !playerTeamFilter) return;

  teamCheckboxList.innerHTML = "";
  primaryTeamSelect.innerHTML = `<option value="">Select primary team</option>`;
  playerTeamFilter.innerHTML = `<option value="all">All Teams</option>`;

  teamsCache.forEach((team) => {
    const teamLabel = `${team.name || "Unnamed Team"} (${team.ageGroup || "No age group"})`;

    const row = document.createElement("label");
    row.className = "checkbox-row";

    row.innerHTML = `
      <input
        type="checkbox"
        class="player-team-checkbox"
        value="${team.id}"
      />
      <span>
        <strong>${team.name || "Unnamed Team"}</strong>
        <small>${team.ageGroup || "No age group"}</small>
      </span>
    `;

    teamCheckboxList.appendChild(row);

    const primaryOption = document.createElement("option");
    primaryOption.value = team.id;
    primaryOption.textContent = teamLabel;
    primaryTeamSelect.appendChild(primaryOption);

    const filterOption = document.createElement("option");
    filterOption.value = team.id;
    filterOption.textContent = `${team.name || "Unnamed Team"} • ${team.ageGroup || "No age group"}`;
    playerTeamFilter.appendChild(filterOption);
  });
}

function renderPlayerUsers() {
  if (!linkedUserId) return;

  if (activeProfile.role !== "director") {
    linkedUserId.innerHTML = `<option value="">Only directors can link player login accounts</option>`;
    linkedUserId.disabled = true;
    return;
  }

  linkedUserId.disabled = false;
  linkedUserId.innerHTML = `<option value="">No linked login account</option>`;

  usersCache.forEach((user) => {
    const option = document.createElement("option");
    option.value = user.uid || user.id;
    option.textContent = `${user.fullName || user.email || "Unnamed User"} (${user.email || "No email"})`;
    linkedUserId.appendChild(option);
  });
}

function getStatusClass(status) {
  const cleanStatus = String(status || "available").toLowerCase();

  if (cleanStatus === "available") return "status-available";
  if (cleanStatus === "rehab") return "status-rehab";
  if (cleanStatus === "injured") return "status-injured";
  if (cleanStatus === "unavailable") return "status-unavailable";

  return "status-available";
}

function renderPlayers() {
  const team1List = document.getElementById("team1PlayerList");
  const team2List = document.getElementById("team2PlayerList");
  const team1Heading = document.getElementById("team1Heading");
  const team2Heading = document.getElementById("team2Heading");
  const team1Count = document.getElementById("team1Count");
  const team2Count = document.getElementById("team2Count");
  const extraContainer = document.getElementById("extraTeamsContainer");

  // Fallback to legacy single list if new layout not present
  if (!team1List || !team2List) {
    if (!playerList) return;
    playerList.style.display = "";
    playerList.innerHTML = "";
    if (!playersCache.length) {
      playerList.innerHTML = `<div class="app-card"><strong>No players added yet.</strong><p>Create your first player profile using the form above.</p></div>`;
    }
    playersCache.forEach((player) => {
      const item = document.createElement("article");
      item.className = "player-profile-card elite-player-card";
      item.innerHTML = buildPlayerCardHTML(player);
      playerList.appendChild(item);
    });
    return;
  }

  // Sort teams: use creation order from teamsCache (index 0 = 1st, 1 = 2nd, rest = extra)
  const team1 = teamsCache[0] || null;
  const team2 = teamsCache[1] || null;
  const extraTeams = teamsCache.slice(2);

  // Set headings
  if (team1Heading) team1Heading.textContent = team1 ? (team1.name || "1st Team") : "1st Team";
  if (team2Heading) team2Heading.textContent = team2 ? (team2.name || "2nd Team") : "2nd Team";

  function getPlayersForTeam(teamId) {
    if (!teamId) return [];
    return playersCache.filter((player) => {
      const ids = player.teamIds || (player.teamId ? [player.teamId] : []);
      return ids.includes(teamId);
    });
  }

  function renderIntoList(container, players, emptyLabel) {
    container.innerHTML = "";
    if (!players.length) {
      container.innerHTML = `<div class="app-card"><strong>No players in ${emptyLabel}.</strong><p>Add players and assign them to this team.</p></div>`;
      return;
    }
    players.forEach((player) => {
      const item = document.createElement("article");
      item.className = "player-profile-card elite-player-card";
      item.innerHTML = buildPlayerCardHTML(player);
      container.appendChild(item);
    });
  }

  const team1Players = team1 ? getPlayersForTeam(team1.id) : [];
  const team2Players = team2 ? getPlayersForTeam(team2.id) : [];

  if (team1Count) team1Count.textContent = team1Players.length;
  if (team2Count) team2Count.textContent = team2Players.length;

  renderIntoList(team1List, team1Players, team1 ? (team1.name || "1st Team") : "1st Team");
  renderIntoList(team2List, team2Players, team2 ? (team2.name || "2nd Team") : "2nd Team");

  // Extra teams
  if (extraContainer) {
    extraContainer.innerHTML = "";
    extraTeams.forEach((team) => {
      const teamPlayers = getPlayersForTeam(team.id);
      const section = document.createElement("div");
      section.style.marginTop = "2rem";
      section.innerHTML = `
        <div class="team-column-header" style="margin-bottom:1rem">
          <h3>${team.name || "Team"}</h3>
          <span class="player-count-badge">${teamPlayers.length}</span>
        </div>
      `;
      const list = document.createElement("div");
      list.className = "list-stack elite-player-list";
      if (!teamPlayers.length) {
        list.innerHTML = `<div class="app-card"><strong>No players in ${team.name || "this team"}.</strong></div>`;
      } else {
        teamPlayers.forEach((player) => {
          const item = document.createElement("article");
          item.className = "player-profile-card elite-player-card";
          item.innerHTML = buildPlayerCardHTML(player);
          list.appendChild(item);
        });
      }
      section.appendChild(list);
      extraContainer.appendChild(section);
    });
  }
}

function buildPlayerCardHTML(player) {
  const age = player.dob ? calculateAgeFromDob(player.dob) : "N/A";
  const teamName =
    player.teamNames?.length
      ? player.teamNames.join(", ")
      : getTeamName(player.teamId);

  return `
      <div class="player-card-header">
        <div>
          <h3>${getPlayerName(player)}</h3>
          <p>${teamName} • ${player.ageGroup || "No age group"}</p>
        </div>

        <span class="status-pill ${getStatusClass(player.status)}">
          ${player.status || "available"}
        </span>
      </div>

      <div class="player-card-grid elite-profile-grid">
        <div>
          <span>Position</span>
          <strong>${player.position || "No position"}</strong>
        </div>

        <div>
          <span>Jersey</span>
          <strong>${player.jerseyNumber || "N/A"}</strong>
        </div>

        <div>
          <span>Age</span>
          <strong>${age}</strong>
        </div>

        <div>
          <span>Height</span>
          <strong>${player.heightCm || "N/A"} cm</strong>
        </div>

        <div>
          <span>Weight</span>
          <strong>${player.weightKg || "N/A"} kg</strong>
        </div>

        <div>
          <span>Dominant Side</span>
          <strong>${player.dominantSide || "N/A"}</strong>
        </div>
      </div>

      <div class="player-card-footer">
        <p>
          <strong>Guardian:</strong>
          ${player.guardianName || "N/A"} • ${player.guardianPhone || "No phone"}
        </p>

        <p>
          <strong>Medical:</strong>
          ${player.medicalNotes || "No notes"}
        </p>

        <p>
          <strong>Linked Account:</strong>
          ${player.userId ? "Player login linked" : "No player login linked"}
        </p>
      </div>

      <div class="player-card-actions record-actions">
        <a href="player-detail.html?id=${player.id}" class="btn-primary">
          View Profile
        </a>

        <button class="btn-secondary edit-player-btn" data-id="${player.id}" type="button">
          Edit
        </button>

        <button class="btn-danger delete-player-btn" data-id="${player.id}" type="button">
          Delete
        </button>
      </div>
    `;
}

async function refreshPlayersOnly() {
  if (!activeProfile?.organisationId) {
    throw new Error("No organisation linked to this user.");
  }
  
  const playersQuery = query(
    collection(db, "players"),
    where("organisationId", "==", activeProfile.organisationId),
    orderBy("createdAt", "desc")
  );

  const playersSnapshot = await getDocs(playersQuery);

  playersCache = playersSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((player) => canAccessPlayer(player));

  renderPlayers();
}

async function canCreateAnotherPlayer() {
  if (!activeProfile?.organisationId) return false;

  const organisationRef = doc(db, "organisations", activeProfile.organisationId);
  const organisationSnap = await getDoc(organisationRef);

  if (!organisationSnap.exists()) {
    showToast("Organisation not found.", "error");
    return false;
  }

  const organisation = organisationSnap.data();
  const subscription = organisation.subscription || {};
  const limits = subscription.limits || {};

  const maxPlayers = Number(limits.maxPlayers || 0);

  if (!maxPlayers) {
    showToast("No player limit found for this subscription.", "warning");
    return false;
  }

  if (playersCache.length >= maxPlayers) {
    showToast(
      `Your current subscription allows a maximum of ${maxPlayers} player(s). Please upgrade your plan to add more players.`,
      "warning"
    );

    return false;
  }

  return true;
}

playerForm?.addEventListener("submit", async function (event) {
  event.preventDefault();

  if (!activeProfile) {
    showToast("User profile not loaded yet.", "warning");
    return;
  }

  const playerData = getFormData();

  if (!playerData.firstName || !playerData.lastName) {
    showToast("Please enter the player's first name and last name.", "warning");
    return;
  }

  if (!playerData.teamIds.length) {
    showToast("Please select at least one team.", "warning");
    return;
  }

  if (!playerData.primaryTeamId) {
    showToast("Please select a primary team.", "warning");
    return;
  }

  if (!playerData.position) {
    showToast("Please select a position.", "warning");
    return;
  }

  if (!playerData.teamIds.every((teamId) => canAccessTeam(teamId))) {
    showToast("You do not have access to this team.", "error");
    return;
  }

  if (playerAlreadyExistsInTeam(playerData)) {
    showToast(
      "This player already exists in the selected team. You can add the same player to another team, but not duplicate them in the same team.",
      "warning"
    );
    return;
  }

  setButtonLoading(true, editingPlayerId ? "Updating..." : "Saving...");

  try {
    if (!editingPlayerId) {
      const allowedToCreatePlayer = await canCreateAnotherPlayer();

      if (!allowedToCreatePlayer) {
        setButtonLoading(false);
        return;
      }
    }

    let savedPlayerId = editingPlayerId;

    if (editingPlayerId) {
      await updateDoc(doc(db, "players", editingPlayerId), {
        ...playerData,
        updatedAt: serverTimestamp()
      });

      playersCache = playersCache.map((player) =>
        player.id === editingPlayerId
          ? {
              ...player,
              ...playerData,
              updatedAt: new Date()
            }
          : player
      );

      showToast("Player profile updated successfully.", "success");
    } else {
      const playerRef = await addDoc(collection(db, "players"), {
        ...playerData,
        sport: "rugby",
        organisationId: activeProfile.organisationId,
        createdBy: activeProfile.uid,
        createdAt: serverTimestamp(),
        updatedAt: serverTimestamp()
      });

      savedPlayerId = playerRef.id;

      playersCache.unshift({
        id: playerRef.id,
        ...playerData,
        sport: "rugby",
        organisationId: activeProfile.organisationId,
        createdBy: activeProfile.uid,
        createdAt: new Date(),
        updatedAt: new Date()
      });

      showToast("Player profile saved successfully.", "success");
    }

    if (playerData.userId) {
      await updateDoc(doc(db, "users", playerData.userId), {
        playerId: savedPlayerId,
        assignedPlayerIds: [savedPlayerId],
        assignedTeamIds: playerData.teamIds || [],
        updatedAt: serverTimestamp()
      });
    }

    resetFormMode();
    await refreshPlayersOnly();
  } catch (error) {
    console.error("Error saving player:", error);
    showToast("Could not save player: " + error.message, "error");
  } finally {
    setButtonLoading(false);
  }
});

document.addEventListener("click", async function (event) {
  // Only handle player card buttons
  if (!event.target.closest(".edit-player-btn") && !event.target.closest(".delete-player-btn")) return;

  const editBtn = event.target.closest(".edit-player-btn");
  const deleteBtn = event.target.closest(".delete-player-btn");

  if (editBtn) {
    const selectedPlayerId = editBtn.dataset.id;
    const player = playersCache.find((item) => item.id === selectedPlayerId);

    if (player) {
      populateForm(player);
    }
  }

  if (deleteBtn) {
    const selectedPlayerId = deleteBtn.dataset.id;

    const confirmed = confirm("Are you sure you want to delete this player profile?");
    if (!confirmed) return;

    deleteBtn.disabled = true;
    deleteBtn.textContent = "Deleting...";

    try {
      await deleteDoc(doc(db, "players", selectedPlayerId));

      playersCache = playersCache.filter((player) => player.id !== selectedPlayerId);

      renderPlayers();
      showToast("Player deleted.", "success");
    } catch (error) {
      console.error("Error deleting player:", error);
      showToast("Could not delete player: " + error.message, "error");
    } finally {
      deleteBtn.disabled = false;
      deleteBtn.textContent = "Delete";
    }
  }
});

playerTeamFilter?.addEventListener("change", renderPlayers);

requireAuth(async function (user, profile) {
  activeProfile = profile;
  setupLogoutButton();

  showLoader("Loading players...");

  if (playerList) {
    playerList.innerHTML = `<div class="app-card">Loading players...</div>`;
  }

  try {
    await loadPageData();
    renderTeamDropdowns();
    renderPlayerUsers();
    renderPlayers();
    resetFormMode();
  } catch (error) {
    console.error("Players page load error:", error);

    if (playerList) {
      playerList.innerHTML = `
        <div class="app-card">
          <strong>Error loading players.</strong>
          <p>${error.message}</p>
        </div>
      `;
    }

    showToast("Could not load players: " + error.message, "error");
  } finally {
    hideLoader();
  }
});