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

const elements = {
  lowWellness: document.getElementById("overviewLowWellness"),
  lowAttendance: document.getElementById("overviewLowAttendance"),
  trainingLoad: document.getElementById("overviewTrainingLoad"),
  loadRisk: document.getElementById("overviewLoadRisk"),
  wellnessChart: document.getElementById("overviewWellnessChart"),
  trainingLoadChart: document.getElementById("overviewTrainingLoadChart"),
  recentActivityList: document.getElementById("overviewRecentActivityList")
};

let activeProfile = null;
let wellnessChartInstance = null;
let trainingLoadChartInstance = null;

const CHART_THEME = {
  ready: "rgba(34,197,94,0.85)",
  warning: "rgba(245,158,11,0.85)",
  danger: "rgba(239,68,68,0.85)",
  primary: "rgba(56,189,248,0.85)",
  primarySoft: "rgba(56,189,248,0.16)",
  text: "#ffffff",
  muted: "#cbd5e1",
  surface: "#0f172a",
  grid: "rgba(255,255,255,0.06)"
};

function safeText(value, fallback = "") {
  if (value === null || value === undefined || value === "") return fallback;
  return String(value);
}

function escapeHTML(value) {
  return String(value ?? "")
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}

function setText(element, value) {
  if (!element) return;
  element.textContent = value;
}

async function getCollectionRecords(collectionName) {
  if (!activeProfile?.organisationId) return [];

  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 canAccessPlayer(player) {
  if (!activeProfile || !player) return false;

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

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

  if (role === "coach") {
    return Boolean(player.teamId && assignedTeamIds.includes(player.teamId));
  }

  if (role === "biokineticist") {
    return (
      Boolean(player.teamId && assignedTeamIds.includes(player.teamId)) ||
      Boolean(player.id && assignedPlayerIds.includes(player.id))
    );
  }

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

  return false;
}

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

function groupByPlayerId(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 getLatestByPlayerId(records) {
  const map = new Map();

  records.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;

  const sleep = Number(record.sleep || 0);
  const fatigue = Number(record.fatigue || 0);
  const soreness = Number(record.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 getLoadRisk(averageLoad) {
  if (averageLoad >= 500) return "Overload";
  if (averageLoad >= 350) return "High";
  if (averageLoad >= 180) return "Optimal";
  if (averageLoad > 0) return "Low";
  return "No Data";
}

function getBaseChartOptions(extraOptions = {}) {
  return {
    responsive: true,
    maintainAspectRatio: false,
    animation: {
      duration: 900,
      easing: "easeOutQuart"
    },
    plugins: {
      tooltip: {
        backgroundColor: CHART_THEME.surface,
        borderColor: "rgba(56,189,248,0.25)",
        borderWidth: 1,
        titleColor: CHART_THEME.text,
        bodyColor: CHART_THEME.muted,
        padding: 14,
        displayColors: true
      }
    },
    ...extraOptions
  };
}

function renderWellnessChart(goodCount, moderateCount, poorCount) {
  if (!elements.wellnessChart || typeof Chart === "undefined") return;

  const total = goodCount + moderateCount + poorCount;

  if (!total) {
    goodCount = 0;
    moderateCount = 0;
    poorCount = 1;
  }

  if (wellnessChartInstance) {
    wellnessChartInstance.destroy();
  }

  wellnessChartInstance = new Chart(elements.wellnessChart, {
    type: "bar",
    data: {
      labels: ["Good", "Moderate", "Poor"],
      datasets: [
        {
          label: "Players",
          data: [goodCount, moderateCount, poorCount],
          backgroundColor: [
            CHART_THEME.ready,
            CHART_THEME.warning,
            CHART_THEME.danger
          ],
          borderRadius: 14
        }
      ]
    },
    options: getBaseChartOptions({
      plugins: {
        legend: { display: false },
        tooltip: getBaseChartOptions().plugins.tooltip
      },
      scales: {
        y: {
          beginAtZero: true,
          ticks: {
            color: CHART_THEME.muted,
            precision: 0
          },
          grid: { color: CHART_THEME.grid }
        },
        x: {
          ticks: { color: CHART_THEME.text },
          grid: { display: false }
        }
      }
    })
  });
}

function renderTrainingLoadChart(trainingSessions) {
  if (!elements.trainingLoadChart || typeof Chart === "undefined") return;

  if (trainingLoadChartInstance) {
    trainingLoadChartInstance.destroy();
  }

  const sortedSessions = [...trainingSessions]
    .sort((a, b) => getDateValue(a) - getDateValue(b))
    .slice(-7);

  let labels = sortedSessions.map((session) => {
    if (!session.date) return "Session";

    const date = new Date(session.date);
    return `${date.getDate()}/${date.getMonth() + 1}`;
  });

  let loads = sortedSessions.map((session) => Number(session.sessionLoad || 0));

  if (!loads.length) {
    labels = ["No Data"];
    loads = [0];
  }

  trainingLoadChartInstance = new Chart(elements.trainingLoadChart, {
    type: "line",
    data: {
      labels,
      datasets: [
        {
          label: "Training Load",
          data: loads,
          borderColor: "#38bdf8",
          backgroundColor: CHART_THEME.primarySoft,
          fill: true,
          tension: 0.35,
          pointRadius: 5,
          pointHoverRadius: 7,
          pointBackgroundColor: "#38bdf8"
        }
      ]
    },
    options: getBaseChartOptions({
      plugins: {
        legend: { display: false },
        tooltip: getBaseChartOptions().plugins.tooltip
      },
      scales: {
        y: {
          beginAtZero: true,
          ticks: { color: CHART_THEME.muted },
          grid: { color: CHART_THEME.grid }
        },
        x: {
          ticks: { color: CHART_THEME.text },
          grid: { display: false }
        }
      }
    })
  });
}

function renderRecentActivity(attendance, wellness, injuries, trainingSessions) {
  if (!elements.recentActivityList) return;

  const activities = [
    ...attendance.map((record) => ({
      type: "Attendance",
      title: safeText(record.playerName, "Unknown Player"),
      detail: `${safeText(record.teamName, "No team")} • ${safeText(record.status, "No status")} • ${safeText(record.date, "No date")}`,
      date: getDateValue(record),
      href: "attendance.html"
    })),

    ...wellness.map((record) => ({
      type: "Wellness",
      title: safeText(record.playerName, "Unknown Player"),
      detail: `${safeText(record.teamName, "No team")} • Sleep ${safeText(record.sleep, "-")}/5 • Fatigue ${safeText(record.fatigue, "-")}/5 • Soreness ${safeText(record.soreness, "-")}/5`,
      date: getDateValue(record),
      href: "wellness.html"
    })),

    ...injuries.map((record) => ({
      type: "Injury",
      title: safeText(record.playerName, "Unknown Player"),
      detail: `${safeText(record.teamName, "No team")} • ${safeText(record.type || record.injuryType, "No type")} • ${safeText(record.status, "No status")}`,
      date: getDateValue(record),
      href: "injuries.html"
    })),

    ...trainingSessions.map((session) => ({
      type: "Training",
      title: safeText(session.teamName, "Training Session"),
      detail: `${safeText(session.date, "No date")} • Load ${safeText(session.sessionLoad, 0)} • ${safeText(session.type, "training")}`,
      date: getDateValue(session),
      href: "training.html"
    }))
  ];

  activities.sort((a, b) => b.date - a.date);

  const latest = activities.slice(0, 12);

  elements.recentActivityList.innerHTML = "";

  if (!latest.length) {
    elements.recentActivityList.innerHTML = `<div class="app-card">No recent activity yet.</div>`;
    return;
  }

  latest.forEach((activity) => {
    const item = document.createElement("a");
    item.className = "recent-activity-item";
    item.href = activity.href;

    item.innerHTML = `
      <div>
        <span class="activity-type">${escapeHTML(activity.type)}</span>
        <h3>${escapeHTML(activity.title)}</h3>
        <p>${escapeHTML(activity.detail)}</p>
      </div>
    `;

    elements.recentActivityList.appendChild(item);
  });
}

async function loadPerformanceOverview() {
  showLoader("Loading performance overview...");

  try {
    const [
      allPlayers,
      allAttendance,
      allTrainingAttendance,
      allWellness,
      allInjuries,
      allTrainingSessions
    ] = await Promise.all([
      getCollectionRecords("players"),
      getCollectionRecords("attendance"),
      getCollectionRecords("trainingAttendance"),
      getCollectionRecords("wellness"),
      getCollectionRecords("injuries"),
      getCollectionRecords("trainingSessions")
    ]);

    const players = allPlayers.filter((player) => canAccessPlayer(player));

    const accessiblePlayerIds = new Set(players.map((player) => player.id));
    const accessibleTeamIds = new Set(players.map((player) => player.teamId).filter(Boolean));

    const attendance = allAttendance.filter((record) =>
      accessiblePlayerIds.has(record.playerId)
    );

    const trainingAttendance = allTrainingAttendance.filter((record) =>
      accessiblePlayerIds.has(record.playerId)
    );

    const combinedAttendance = [...attendance, ...trainingAttendance];

    const wellness = allWellness.filter((record) =>
      accessiblePlayerIds.has(record.playerId)
    );

    const injuries = allInjuries.filter((record) =>
      accessiblePlayerIds.has(record.playerId)
    );

    const trainingSessions = allTrainingSessions.filter((session) =>
      accessibleTeamIds.has(session.teamId)
    );

    const attendanceByPlayer = groupByPlayerId(combinedAttendance);
    const latestWellnessByPlayer = getLatestByPlayerId(wellness);

    let lowWellnessCount = 0;
    let lowAttendanceCount = 0;
    let goodWellness = 0;
    let moderateWellness = 0;
    let poorWellness = 0;

    players.forEach((player) => {
      const playerAttendance = attendanceByPlayer.get(player.id) || [];

      const presentCount = playerAttendance.filter((record) =>
        record.status === "present"
      ).length;

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

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

      if (wellnessScore >= 75) {
        goodWellness++;
      } else if (wellnessScore >= 50) {
        moderateWellness++;
      } else {
        poorWellness++;
      }

      if (wellnessScore < 50) lowWellnessCount++;
      if (attendancePercentage < 65) lowAttendanceCount++;
    });

    const recentSessions = [...trainingSessions]
      .sort((a, b) => getDateValue(b) - getDateValue(a))
      .slice(0, 10);

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

    const averageTrainingLoad = recentSessions.length
      ? Math.round(totalLoad / recentSessions.length)
      : 0;

    setText(elements.lowWellness, lowWellnessCount);
    setText(elements.lowAttendance, lowAttendanceCount);
    setText(elements.trainingLoad, averageTrainingLoad);
    setText(elements.loadRisk, getLoadRisk(averageTrainingLoad));

    renderWellnessChart(goodWellness, moderateWellness, poorWellness);
    renderTrainingLoadChart(trainingSessions);
    renderRecentActivity(combinedAttendance, wellness, injuries, trainingSessions);
  } catch (error) {
    console.error("Performance overview error:", error);
    showToast("Could not load performance overview: " + error.message, "error");

    if (elements.recentActivityList) {
      elements.recentActivityList.innerHTML = `
        <div class="app-card">
          <strong>Could not load performance overview.</strong>
          <p>${escapeHTML(error.message)}</p>
        </div>
      `;
    }
  } finally {
    hideLoader();
  }
}

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

  setupLogoutButton();

  await loadPerformanceOverview();
});