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 reportList = document.getElementById("reportList");
const reportTeamFilter = document.getElementById("reportTeamFilter");

const reportTotalPlayers = document.getElementById("reportTotalPlayers");
const reportReadyPlayers = document.getElementById("reportReadyPlayers");
const reportMonitorPlayers = document.getElementById("reportMonitorPlayers");
const reportUnavailablePlayers = document.getElementById("reportUnavailablePlayers");

const exportCsvBtn = document.getElementById("exportCsvBtn");
const printReportBtn = document.getElementById("printReportBtn");

let activeProfile = null;

let teamsCache = [];
let playersCache = [];
let attendanceCache = [];
let trainingAttendanceCache = [];
let wellnessCache = [];
let injuriesCache = [];

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 getTeamName(teamId) {
  const team = teamsCache.find((item) => item.id === teamId);
  return team ? team.name : "Unassigned";
}

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

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);
}

function buildPlayerRecordMap(records) {
  const map = new Map();

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

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

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

  return map;
}

function getReadinessRows(filteredPlayers) {
  const attendanceByPlayer = buildPlayerRecordMap([
    ...attendanceCache,
    ...trainingAttendanceCache
  ]);

  const wellnessByPlayer = buildPlayerRecordMap(wellnessCache);
  const injuriesByPlayer = buildPlayerRecordMap(injuriesCache);

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

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

    const attendance = attendanceRecords.length
      ? Math.round((present / attendanceRecords.length) * 100)
      : 0;

    const wellnessRecords = wellnessByPlayer.get(player.id) || [];

    const latestWellness = [...wellnessRecords].sort((a, b) => {
      return getDateValue(b) - getDateValue(a);
    })[0];

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

    const wellness = latestWellness
      ? sleep + fatigue + soreness
      : 0;

    const activeInjuries = (injuriesByPlayer.get(player.id) || []).filter((record) => {
      const status = String(record.status || "").toLowerCase();

      return (
        status !== "cleared" &&
        status !== "closed" &&
        status !== "resolved"
      );
    });

    const injuries = activeInjuries.length;
    const playerStatus = String(player.status || "available").toLowerCase();

    let readiness = "Ready";
    let readinessClass = "readiness-ready";

    if (
      playerStatus === "injured" ||
      playerStatus === "rehab" ||
      injuries > 0
    ) {
      readiness = "Unavailable";
      readinessClass = "readiness-danger";
    } else if (attendance < 70 || wellness >= 11) {
      readiness = "Monitor";
      readinessClass = "readiness-monitor";
    }

    return {
      player,
      attendance,
      wellness,
      injuries,
      readiness,
      readinessClass
    };
  });
}

async function loadData() {
  showLoader("Loading readiness report...");

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

  try {
    const [
      teams,
      players,
      attendance,
      trainingAttendance,
      wellness,
      injuries
    ] = await Promise.all([
      getRecords("teams"),
      getRecords("players"),
      getRecords("attendance"),
      getRecords("trainingAttendance"),
      getRecords("wellness"),
      getRecords("injuries")
    ]);

    teamsCache = teams.filter((team) => canAccessTeam(team.id));
    playersCache = players.filter((player) => canAccessTeam(player.teamId));

    const accessiblePlayerIds = new Set(playersCache.map((player) => player.id));

    attendanceCache = attendance.filter((record) => {
      return accessiblePlayerIds.has(record.playerId);
    });

    trainingAttendanceCache = trainingAttendance.filter((record) => {
      return accessiblePlayerIds.has(record.playerId);
    });

    wellnessCache = wellness.filter((record) => {
      return accessiblePlayerIds.has(record.playerId);
    });

    injuriesCache = injuries.filter((record) => {
      return accessiblePlayerIds.has(record.playerId);
    });

    renderTeamFilter();
    renderReport();
  } catch (error) {
    console.error("Readiness report error:", error);

    reportList.innerHTML = `
      <div class="list-item">
        Error loading readiness report: ${error.message}
      </div>
    `;

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

function renderTeamFilter() {
  if (!reportTeamFilter) return;

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

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

function renderReport() {
  if (!reportList) return;

  const selectedTeam = reportTeamFilter?.value || "all";

  const filteredPlayers = playersCache.filter((player) => {
    return selectedTeam === "all" || player.teamId === selectedTeam;
  });

  const rows = getReadinessRows(filteredPlayers).sort((a, b) => {
    return getReadinessWeight(b.readiness) - getReadinessWeight(a.readiness);
  });

  reportTotalPlayers.textContent = rows.length;
  reportReadyPlayers.textContent = rows.filter((row) => row.readiness === "Ready").length;
  reportMonitorPlayers.textContent = rows.filter((row) => row.readiness === "Monitor").length;
  reportUnavailablePlayers.textContent = rows.filter((row) => row.readiness === "Unavailable").length;

  reportList.innerHTML = "";

  if (!rows.length) {
    reportList.innerHTML = `
      <div class="list-item">
        <strong>No players found.</strong>
        <p>No players are available for this team filter.</p>
      </div>
    `;
    return;
  }

  rows.forEach((row) => {
    const player = row.player;

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

    item.innerHTML = `
      <div>
        <h3>${getPlayerName(player)}</h3>
        <p>
          ${getTeamName(player.teamId)}
          <span class="record-separator">&bull;</span>
          ${player.position || "No position"}
          <span class="record-separator">&bull;</span>
          ${player.ageGroup || "No group"}
        </p>
      </div>

      <div class="report-metrics">
        <span class="report-pill ${row.readinessClass}">
          ${row.readiness}
        </span>

        <span>Attendance: ${row.attendance}%</span>
        <span>Wellness: ${row.wellness || "-"}/15</span>
        <span>Injuries: ${row.injuries}</span>
      </div>
    `;

    reportList.appendChild(item);
  });
}

function getReadinessWeight(readiness) {
  if (readiness === "Unavailable") return 3;
  if (readiness === "Monitor") return 2;
  return 1;
}

function exportCSV() {
  const selectedTeam = reportTeamFilter.value || "all";

  const filteredPlayers = playersCache.filter((player) => {
    return selectedTeam === "all" || player.teamId === selectedTeam;
  });

  const rows = getReadinessRows(filteredPlayers);

  let csvContent =
    "Player,Team,Position,Age Group,Attendance,Wellness,Injuries,Readiness\n";

  rows.forEach((row) => {
    const player = row.player;

    const csvRow = [
      `"${getPlayerName(player)}"`,
      `"${getTeamName(player.teamId)}"`,
      `"${player.position || ""}"`,
      `"${player.ageGroup || ""}"`,
      `"${row.attendance}%"`,
      `"${row.wellness || "-"}"`,
      `"${row.injuries}"`,
      `"${row.readiness}"`
    ];

    csvContent += csvRow.join(",") + "\n";
  });

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

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

  link.setAttribute("href", url);
  link.setAttribute(
    "download",
    `selection-readiness-${new Date().toISOString().slice(0, 10)}.csv`
  );

  link.style.visibility = "hidden";
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);

  URL.revokeObjectURL(url);
}

reportTeamFilter?.addEventListener("change", renderReport);

printReportBtn?.addEventListener("click", function () {
  window.print();
});

exportCsvBtn?.addEventListener("click", exportCSV);

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