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

const urlParams = new URLSearchParams(window.location.search);
const teamId = urlParams.get("id");

const teamName = document.getElementById("teamName");
const teamMeta = document.getElementById("teamMeta");

const teamPlayers = document.getElementById("teamPlayers");
const teamAttendance = document.getElementById("teamAttendance");
const teamWellness = document.getElementById("teamWellness");
const teamInjuries = document.getElementById("teamInjuries");
const teamTrainingLoad = document.getElementById("teamTrainingLoad");
const teamRiskScore = document.getElementById("teamRiskScore");
const teamReadinessList = document.getElementById("teamReadinessList");

const teamAttendanceChart = document.getElementById("teamAttendanceChart");
const teamWellnessChart = document.getElementById("teamWellnessChart");
const teamTrainingLoadChart = document.getElementById("teamTrainingLoadChart");
const teamReadinessChart = document.getElementById("teamReadinessChart");

const teamInsights = document.getElementById("teamInsights");
const printTeamPerformanceBtn = document.getElementById("printTeamPerformanceBtn");
const exportTeamPerformanceCsvBtn = document.getElementById("exportTeamPerformanceCsvBtn");

let activeProfile = null;
let currentTeam = null;

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

let attendanceChartInstance = null;
let wellnessChartInstance = null;
let trainingLoadChartInstance = null;
let readinessChartInstance = null;

function canRenderChart() {
  return typeof Chart !== "undefined";
}

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

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

  if (role === "coach" || role === "biokineticist") {
    return assignedTeamIds.includes(id);
  }

  return false;
}

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 getPlayerName(player) {
  return `${player.firstName || ""} ${player.lastName || ""}`.trim() || "Unnamed Player";
}

function isActiveInjury(record) {
  const status = String(record.status || "").toLowerCase();

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

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 getLatestWellnessByPlayer() {
  const map = new Map();

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

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

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

  return map;
}

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

  return (
    Number(record.sleep || 0) +
    Number(record.fatigue || 0) +
    Number(record.soreness || 0)
  );
}

function getReadinessClass(readiness) {
  if (readiness === "Ready") return "readiness-ready";
  if (readiness === "Monitor") return "readiness-monitor";

  return "readiness-danger";
}

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

  return 1;
}

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

  const latestWellnessByPlayer = getLatestWellnessByPlayer();
  const injuriesByPlayer = buildPlayerRecordMap(injuriesCache);

  return playersCache.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 latestWellness = latestWellnessByPlayer.get(player.id);
    const wellness = calculateWellnessScore(latestWellness);

    const injuries = (injuriesByPlayer.get(player.id) || []).filter((record) => {
      return isActiveInjury(record);
    }).length;

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

    let readiness = "Ready";

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

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

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

  const snapshot = await getDocs(q);

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

async function loadTeam() {
  const teamSnap = await getDoc(doc(db, "teams", teamId));

  if (!teamSnap.exists()) {
    teamName.textContent = "Team not found";
    return false;
  }

  currentTeam = {
    id: teamSnap.id,
    ...teamSnap.data()
  };

  if (currentTeam.organisationId !== activeProfile.organisationId) {
    showToast("This team does not belong to your organisation.", "error");
    window.location.href = "teams.html";
    return false;
  }

  if (!canAccessTeam(currentTeam.id)) {
    showToast("You do not have access to this team.", "error");
    window.location.href = "teams.html";
    return false;
  }

  teamName.textContent = currentTeam.name || "Unnamed Team";

  teamMeta.textContent = `
    ${currentTeam.ageGroup || "No age group"}
    •
    ${currentTeam.sport || "rugby"}
  `;

  return true;
}

async function loadTeamData() {
  const [
    players,
    teamAttendanceRecords,
    teamTrainingAttendanceRecords,
    teamWellnessRecords,
    teamInjuryRecords,
    teamTrainingSessions
  ] = await Promise.all([
    getTeamRecords("players"),
    getTeamRecords("attendance"),
    getTeamRecords("trainingAttendance"),
    getTeamRecords("wellness"),
    getTeamRecords("injuries"),
    getTeamRecords("trainingSessions")
  ]);

  playersCache = players.sort((a, b) => {
    return getPlayerName(a).toLowerCase().localeCompare(getPlayerName(b).toLowerCase());
  });

  attendanceCache = teamAttendanceRecords;
  trainingAttendanceCache = teamTrainingAttendanceRecords;
  wellnessCache = teamWellnessRecords;
  injuriesCache = teamInjuryRecords;

  trainingSessionsCache = teamTrainingSessions.sort((a, b) => {
    return getDateValue(a) - getDateValue(b);
  });
}

function calculateTeamRiskScore(rows) {
  let score = 0;

  const allAttendanceRecords = [
    ...attendanceCache,
    ...trainingAttendanceCache
  ];

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

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

  if (attendanceRate < 70) score += 20;
  else if (attendanceRate < 85) score += 10;

  const wellnessAverage = rows.length
    ? rows.reduce((sum, row) => sum + row.wellness, 0) / rows.length
    : 0;

  if (wellnessAverage >= 11) score += 25;
  else if (wellnessAverage >= 7) score += 10;

  const activeInjuries = injuriesCache.filter((record) => isActiveInjury(record));

  if (activeInjuries.length >= 3) score += 25;
  else if (activeInjuries.length > 0) score += 10;

  const totalLoad = trainingSessionsCache.reduce((sum, session) => {
    return sum + Number(session.sessionLoad || 0);
  }, 0);

  const averageLoad = trainingSessionsCache.length
    ? Math.round(totalLoad / trainingSessionsCache.length)
    : 0;

  if (averageLoad >= 500) score += 20;
  else if (averageLoad >= 350) score += 10;

  const unavailableCount = rows.filter((row) => {
    return row.readiness === "Unavailable";
  }).length;

  if (unavailableCount >= 3) score += 20;
  else if (unavailableCount > 0) score += 10;

  return Math.min(score, 100);
}

function renderTeamStats(rows) {
  teamPlayers.textContent = playersCache.length;

  const allAttendanceRecords = [
    ...attendanceCache,
    ...trainingAttendanceCache
  ];

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

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

  teamAttendance.textContent = `${attendanceRate}%`;

  const wellnessAverage = rows.length
    ? rows.reduce((sum, row) => sum + row.wellness, 0) / rows.length
    : 0;

  if (!wellnessAverage) {
    teamWellness.textContent = "No Data";
  } else if (wellnessAverage <= 6) {
    teamWellness.textContent = "Good";
  } else if (wellnessAverage <= 10) {
    teamWellness.textContent = "Watch";
  } else {
    teamWellness.textContent = "Risk";
  }

  const activeInjuries = injuriesCache.filter((record) => isActiveInjury(record));
  teamInjuries.textContent = activeInjuries.length;

  const totalLoad = trainingSessionsCache.reduce((sum, session) => {
    return sum + Number(session.sessionLoad || 0);
  }, 0);

  const averageLoad = trainingSessionsCache.length
    ? Math.round(totalLoad / trainingSessionsCache.length)
    : 0;

  teamTrainingLoad.textContent = averageLoad;

  const riskScore = calculateTeamRiskScore(rows);

  teamRiskScore.textContent = riskScore;
  teamRiskScore.className = "";

  if (riskScore >= 70) {
    teamRiskScore.style.color = "#fca5a5";
  } else if (riskScore >= 35) {
    teamRiskScore.style.color = "#fcd34d";
  } else {
    teamRiskScore.style.color = "#86efac";
  }
}

function renderReadinessList(rows) {
  teamReadinessList.innerHTML = "";

  const sortedRows = [...rows].sort((a, b) => {
    return getReadinessWeight(b.readiness) - getReadinessWeight(a.readiness);
  });

  if (!sortedRows.length) {
    teamReadinessList.innerHTML = `
      <div class="list-item">
        No players found for this team.
      </div>
    `;

    return;
  }

  sortedRows.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>
          ${player.position || "No position"}
          <span class="record-separator">&bull;</span>
          ${player.ageGroup || "No group"}
          <span class="record-separator">&bull;</span>
          ${player.status || "available"}
        </p>
      </div>

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

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

    teamReadinessList.appendChild(item);
  });
}

function destroyChart(chartInstance) {
  if (chartInstance) {
    chartInstance.destroy();
  }
}

function renderAttendanceChart(rows) {
  if (!rows.length || !teamAttendanceChart || !canRenderChart()) return;

  destroyChart(attendanceChartInstance);

  const labels = rows.map((row) => getPlayerName(row.player));
  const data = rows.map((row) => row.attendance);

  attendanceChartInstance = new Chart(teamAttendanceChart, {
    type: "bar",
    data: {
      labels,
      datasets: [
        {
          label: "Attendance %",
          data
        }
      ]
    },
    options: getChartOptions(100)
  });
}

function renderWellnessChart(rows) {
  if (!rows.length || !teamWellnessChart || !canRenderChart()) return;

  destroyChart(wellnessChartInstance);

  const labels = rows.map((row) => getPlayerName(row.player));
  const data = rows.map((row) => row.wellness);

  wellnessChartInstance = new Chart(teamWellnessChart, {
    type: "bar",
    data: {
      labels,
      datasets: [
        {
          label: "Wellness Score",
          data
        }
      ]
    },
    options: getChartOptions(15)
  });
}

function renderTrainingLoadChart() {
  if (!trainingSessionsCache.length || !teamTrainingLoadChart || !canRenderChart()) return;

  destroyChart(trainingLoadChartInstance);

  const labels = trainingSessionsCache.map((session) => {
    return session.date || session.sessionDate || "No date";
  });

  const data = trainingSessionsCache.map((session) => {
    return Number(session.sessionLoad || 0);
  });

  trainingLoadChartInstance = new Chart(teamTrainingLoadChart, {
    type: "line",
    data: {
      labels,
      datasets: [
        {
          label: "Training Load",
          data,
          tension: 0.3,
          fill: false
        }
      ]
    },
    options: getChartOptions()
  });
}

function renderReadinessChart(rows) {
  if (!teamReadinessChart || !canRenderChart()) return;

  destroyChart(readinessChartInstance);

  const readinessTotals = {
    Ready: 0,
    Monitor: 0,
    Unavailable: 0
  };

  rows.forEach((row) => {
    readinessTotals[row.readiness]++;
  });

  readinessChartInstance = new Chart(teamReadinessChart, {
    type: "doughnut",
    data: {
      labels: ["Ready", "Monitor", "Unavailable"],
      datasets: [
        {
          data: [
            readinessTotals.Ready,
            readinessTotals.Monitor,
            readinessTotals.Unavailable
          ]
        }
      ]
    },
    options: {
      responsive: true,
      plugins: {
        legend: {
          labels: {
            color: "#ffffff"
          }
        }
      }
    }
  });
}

function getChartOptions(maxValue) {
  const options = {
    responsive: true,
    plugins: {
      legend: {
        labels: {
          color: "#ffffff"
        }
      }
    },
    scales: {
      y: {
        beginAtZero: true,
        ticks: {
          color: "#ffffff"
        }
      },
      x: {
        ticks: {
          color: "#ffffff"
        }
      }
    }
  };

  if (maxValue) {
    options.scales.y.max = maxValue;
  }

  return options;
}

function renderTeamInsights(rows) {
  const insights = [];

  const attendanceRate = Number(teamAttendance.textContent.replace("%", "") || 0);
  const injuryTotal = Number(teamInjuries.textContent || 0);
  const averageLoad = Number(teamTrainingLoad.textContent || 0);
  const riskScore = Number(teamRiskScore.textContent || 0);

  const readinessTotals = {
    Ready: 0,
    Monitor: 0,
    Unavailable: 0
  };

  rows.forEach((row) => {
    readinessTotals[row.readiness]++;
  });

  const monitorOrUnavailable =
    readinessTotals.Monitor + readinessTotals.Unavailable;

  if (riskScore >= 70) {
    insights.push({
      title: "High Team Risk",
      text: "The overall team risk score is high. Review injuries, attendance, wellness and load before the next match."
    });
  } else if (riskScore >= 35) {
    insights.push({
      title: "Moderate Risk Profile",
      text: "This team has some risk indicators that should be monitored by coaches and support staff."
    });
  }

  if (attendanceRate < 70) {
    insights.push({
      title: "Low Attendance Risk",
      text: "Team attendance is below 70%. This may affect readiness, cohesion and match preparation."
    });
  } else if (attendanceRate >= 85) {
    insights.push({
      title: "Strong Attendance",
      text: "This team has strong attendance, supporting consistent preparation and team cohesion."
    });
  }

  if (teamWellness.textContent === "Risk") {
    insights.push({
      title: "Wellness Risk",
      text: "Team wellness is currently in a risk range. Recovery, fatigue and soreness should be reviewed."
    });
  }

  if (injuryTotal >= 3) {
    insights.push({
      title: "Injury Cluster",
      text: "This team has multiple active injuries. Consider adjusting load, contact exposure or recovery planning."
    });
  }

  if (averageLoad >= 500) {
    insights.push({
      title: "Overload Risk",
      text: "Average training load is very high. Monitor fatigue and injury risk before the next session or match."
    });
  } else if (averageLoad >= 350) {
    insights.push({
      title: "High Training Load",
      text: "Training load is elevated. Ensure recovery and wellness checks are monitored."
    });
  }

  if (monitorOrUnavailable > 0) {
    insights.push({
      title: "Selection Watch",
      text: `${monitorOrUnavailable} player(s) are currently marked as Monitor or Unavailable.`
    });
  }

  if (!insights.length) {
    insights.push({
      title: "Stable Team Profile",
      text: "No major team performance risks are currently detected."
    });
  }

  teamInsights.innerHTML = "";

  insights.forEach((insight) => {
    const item = document.createElement("div");
    item.className = "insight-card elite-card";

    item.innerHTML = `
      <h3>${insight.title}</h3>
      <p>${insight.text}</p>
    `;

    teamInsights.appendChild(item);
  });
}

function exportTeamPerformanceCSV() {
  const rows = getTeamRows();

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

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

    const csvRow = [
      `"${getPlayerName(player)}"`,
      `"${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",
    `team-performance-${currentTeam?.name || "team"}.csv`
  );

  link.style.visibility = "hidden";

  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);

  URL.revokeObjectURL(url);

  showToast("Team performance exported successfully.", "success");
}

function renderPage() {
  const rows = getTeamRows();

  renderTeamStats(rows);
  renderReadinessList(rows);
  renderAttendanceChart(rows);
  renderWellnessChart(rows);
  renderTrainingLoadChart();
  renderReadinessChart(rows);
  renderTeamInsights(rows);
}

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

exportTeamPerformanceCsvBtn?.addEventListener("click", exportTeamPerformanceCSV);

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

  if (!teamId) {
    teamName.textContent = "Invalid Team";
    return;
  }

  showLoader("Loading team performance...");

  try {
    const hasAccess = await loadTeam();

    if (!hasAccess) return;

    await loadTeamData();
    renderPage();
  } catch (error) {
    console.error("Team performance page error:", error);

    teamName.textContent = "Could not load team performance";

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

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