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,
  getDocs,
  query,
  where
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const matchReadinessList = document.getElementById("matchReadinessList");
const matchTeamFilter = document.getElementById("matchTeamFilter");

const matchTotalPlayers = document.getElementById("matchTotalPlayers");
const matchReadyPlayers = document.getElementById("matchReadyPlayers");
const matchMonitorPlayers = document.getElementById("matchMonitorPlayers");
const matchUnavailablePlayers = document.getElementById("matchUnavailablePlayers");

const exportMatchReadinessBtn = document.getElementById("exportMatchReadinessBtn");
const printMatchReadinessBtn = document.getElementById("printMatchReadinessBtn");

let activeProfile = null;
let players = [];
let teams = [];
let sessions = [];
let attendanceRecords = [];
let wellnessEntries = [];
let injuries = [];

function canAccessTeam(teamId) {
  const role = activeProfile?.role;
  const assignedTeamIds = activeProfile?.assignedTeamIds || [];

  if (role === "director") return true;
  if (role === "coach" || role === "biokineticist") return assignedTeamIds.includes(teamId);

  return false;
}

async function getRecords(collectionName) {
  const q = query(
    collection(db, collectionName),
    where("organisationId", "==", activeProfile.organisationId)
  );

  const snapshot = await getDocs(q);

  return snapshot.docs.map((docSnap) => ({
    id: docSnap.id,
    ...docSnap.data()
  }));
}

function getDateValue(record) {
  if (record?.createdAt?.toDate) return record.createdAt.toDate();
  if (record?.createdDate) return new Date(record.createdDate);
  if (record?.date) return new Date(record.date);
  if (record?.sessionDate) return new Date(record.sessionDate);
  return new Date(0);
}

async function loadMatchReadinessReport() {
  if (!matchReadinessList || !matchTeamFilter) return;

  showLoader("Loading match readiness report...");

  matchReadinessList.innerHTML = `
    <div class="app-card">Loading match readiness report...</div>
  `;

  try {
    if (!activeProfile?.organisationId) {
      throw new Error("No organisationId found on user profile.");
    }

    const [
      playersRecords,
      teamsRecords,
      sessionRecords,
      attendanceRecordData,
      trainingAttendanceRecords,
      wellnessRecords,
      injuryRecords
    ] = await Promise.all([
      getRecords("players"),
      getRecords("teams"),
      getRecords("trainingSessions"),
      getRecords("attendance"),
      getRecords("trainingAttendance"),
      getRecords("wellness"),
      getRecords("injuries")
    ]);

    teams = teamsRecords.filter((team) => canAccessTeam(team.id));

    players = playersRecords.filter((player) => {
      return canAccessTeam(player.teamId);
    });

    const accessiblePlayerIds = new Set(players.map((player) => player.id));
    const accessibleTeamIds = new Set(teams.map((team) => team.id));

    sessions = sessionRecords.filter((session) => {
      return accessibleTeamIds.has(session.teamId);
    });

    attendanceRecords = [...attendanceRecordData, ...trainingAttendanceRecords].filter((record) => {
      return accessiblePlayerIds.has(record.playerId);
    });

    wellnessEntries = wellnessRecords.filter((entry) => {
      return accessiblePlayerIds.has(entry.playerId);
    });

    injuries = injuryRecords.filter((injury) => {
      return accessiblePlayerIds.has(injury.playerId);
    });

    populateTeamFilter();
    renderMatchReadinessReport();
  } catch (error) {
    console.error("Match readiness report error:", error);

    matchReadinessList.innerHTML = `
      <div class="app-card">
        <strong>Could not load match readiness report.</strong>
        <p>${error.message}</p>
      </div>
    `;

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

function populateTeamFilter() {
  if (!matchTeamFilter) return;

  matchTeamFilter.innerHTML = `<option value="all">All Teams</option>`;

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

function buildTeamSessionCountMap() {
  const map = new Map();

  sessions.forEach((session) => {
    if (!session.teamId) return;
    map.set(session.teamId, (map.get(session.teamId) || 0) + 1);
  });

  return map;
}

function buildPlayerAttendanceMap() {
  const map = new Map();

  attendanceRecords.forEach((record) => {
    if (!record.playerId) return;

    if (!map.has(record.playerId)) {
      map.set(record.playerId, []);
    }

    map.get(record.playerId).push(record);
  });

  return map;
}

function getLatestWellnessByPlayer() {
  const map = new Map();

  wellnessEntries.forEach((entry) => {
    if (!entry.playerId) return;

    const existing = map.get(entry.playerId);

    if (!existing || getDateValue(entry) > getDateValue(existing)) {
      map.set(entry.playerId, entry);
    }
  });

  return map;
}

function buildActiveInjuryPlayerSet() {
  const set = new Set();

  injuries.forEach((injury) => {
    const status = String(injury.status || "").toLowerCase();

    const isActive =
      status !== "cleared" &&
      status !== "closed" &&
      status !== "resolved";

    if (injury.playerId && isActive) {
      set.add(injury.playerId);
    }
  });

  return set;
}

function getMatchReadinessRows(filteredPlayers) {
  const teamSessionCountMap = buildTeamSessionCountMap();
  const playerAttendanceMap = buildPlayerAttendanceMap();
  const latestWellnessByPlayer = getLatestWellnessByPlayer();
  const activeInjuryPlayerSet = buildActiveInjuryPlayerSet();

  return filteredPlayers.map((player) => {
    const playerAttendance = playerAttendanceMap.get(player.id) || [];

    const presentCount = playerAttendance.filter((record) => {
      return String(record.status || "").toLowerCase() === "present";
    }).length;

    const teamSessionTotal = teamSessionCountMap.get(player.teamId) || 0;

    const totalSessions =
      teamSessionTotal > 0
        ? teamSessionTotal
        : playerAttendance.length;

    const attendanceRate =
      totalSessions > 0
        ? Math.round((presentCount / totalSessions) * 100)
        : 0;

    const latestWellness = latestWellnessByPlayer.get(player.id);
    const wellnessScore = calculateWellnessScore(latestWellness);

    const trainingLoad = presentCount * 75;
    const injuryStatus = activeInjuryPlayerSet.has(player.id) ? "Active" : "Clear";

    const metrics = {
      attendanceRate,
      wellnessScore,
      trainingLoad,
      injuryStatus
    };

    return {
      player,
      ...metrics,
      status: getMatchReadinessStatus(metrics)
    };
  });
}

function renderMatchReadinessReport() {
  const selectedTeam = matchTeamFilter.value || "all";

  const filteredPlayers =
    selectedTeam === "all"
      ? players
      : players.filter((player) => player.teamId === selectedTeam);

  matchReadinessList.innerHTML = "";

  if (!filteredPlayers.length) {
    matchReadinessList.innerHTML = `
      <div class="app-card">
        <strong>No players found.</strong>
        <p>No players are available for this team filter.</p>
      </div>
    `;

    updateStats(0, 0, 0, 0);
    return;
  }

  const rows = getMatchReadinessRows(filteredPlayers).sort((a, b) => {
    return getStatusWeight(b.status.key) - getStatusWeight(a.status.key);
  });

  const readyCount = rows.filter((row) => row.status.key === "ready").length;
  const monitorCount = rows.filter((row) => row.status.key === "monitor").length;
  const unavailableCount = rows.filter((row) => row.status.key === "unavailable").length;

  rows.forEach((row) => {
    const item = document.createElement("div");
    item.className = "elite-readiness-row elite-card";

    item.innerHTML = `
      <div>
        <h3>${getPlayerName(row.player)}</h3>
        <p>${getTeamName(row.player.teamId)} • ${row.player.position || "No position"}</p>
      </div>

      <div class="report-metrics">
        <span class="report-pill ${row.status.className}">
          ${row.status.label}
        </span>

        <span>Attendance: ${row.attendanceRate}%</span>
        <span>Wellness: ${row.wellnessScore}%</span>
        <span>Training Load: ${row.trainingLoad}</span>
        <span>Injury: ${row.injuryStatus}</span>
      </div>
    `;

    matchReadinessList.appendChild(item);
  });

  updateStats(rows.length, readyCount, monitorCount, unavailableCount);
}

function updateStats(total, ready, monitor, unavailable) {
  matchTotalPlayers.textContent = total;
  matchReadyPlayers.textContent = ready;
  matchMonitorPlayers.textContent = monitor;
  matchUnavailablePlayers.textContent = unavailable;
}

function calculateWellnessScore(entry) {
  if (!entry) return 0;

  const sleep = Number(entry.sleep || 0);
  const fatigue = Number(entry.fatigue || 0);
  const soreness = Number(entry.soreness || 0);

  const reverseFatigue = Math.max(0, 6 - fatigue);
  const reverseSoreness = Math.max(0, 6 - soreness);

  const total = sleep + reverseFatigue + reverseSoreness;

  return Math.round((total / 15) * 100);
}

function getMatchReadinessStatus(metrics) {
  if (
    metrics.injuryStatus === "Active" ||
    metrics.attendanceRate < 60 ||
    metrics.wellnessScore < 45
  ) {
    return {
      key: "unavailable",
      label: "Unavailable",
      className: "readiness-danger"
    };
  }

  if (
    metrics.attendanceRate < 80 ||
    metrics.wellnessScore < 70 ||
    metrics.trainingLoad > 450
  ) {
    return {
      key: "monitor",
      label: "Monitor",
      className: "readiness-monitor"
    };
  }

  return {
    key: "ready",
    label: "Ready",
    className: "readiness-ready"
  };
}

function getStatusWeight(key) {
  if (key === "unavailable") return 3;
  if (key === "monitor") return 2;
  return 1;
}

function getPlayerName(player) {
  const firstName = player.firstName || "";
  const lastName = player.lastName || "";

  return (
    player.name ||
    player.fullName ||
    player.displayName ||
    `${firstName} ${lastName}`.trim() ||
    "Unnamed Player"
  );
}

function getTeamName(teamId) {
  const team = teams.find((item) => item.id === teamId);
  return team ? team.name : "No Team";
}

function exportMatchReadinessCsv() {
  const selectedTeam = matchTeamFilter.value || "all";

  const filteredPlayers =
    selectedTeam === "all"
      ? players
      : players.filter((player) => player.teamId === selectedTeam);

  const rows = getMatchReadinessRows(filteredPlayers);

  const csvRows = [
    [
      "Player",
      "Team",
      "Attendance %",
      "Wellness Score",
      "Training Load",
      "Injury Status",
      "Match Readiness"
    ]
  ];

  rows.forEach((row) => {
    csvRows.push([
      getPlayerName(row.player),
      getTeamName(row.player.teamId),
      `${row.attendanceRate}%`,
      `${row.wellnessScore}%`,
      row.trainingLoad,
      row.injuryStatus,
      row.status.label
    ]);
  });

  const csvContent = csvRows
    .map((row) =>
      row.map((value) => `"${String(value).replace(/"/g, '""')}"`).join(",")
    )
    .join("\n");

  const blob = new Blob([csvContent], {
    type: "text/csv;charset=utf-8;"
  });

  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");

  link.href = url;
  link.download = "trytrack-match-readiness-report.csv";
  link.click();

  URL.revokeObjectURL(url);
}

matchTeamFilter?.addEventListener("change", renderMatchReadinessReport);

exportMatchReadinessBtn?.addEventListener("click", exportMatchReadinessCsv);

printMatchReadinessBtn?.addEventListener("click", () => {
  window.print();
});

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

  try {
    await loadMatchReadinessReport();
  } catch (error) {
    console.error("Match readiness startup error:", error);
    hideLoader();
  }
});