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

const overviewTotalTeams = document.getElementById("overviewTotalTeams");
const overviewStrongTeams = document.getElementById("overviewStrongTeams");
const overviewMonitorTeams = document.getElementById("overviewMonitorTeams");
const overviewConcernTeams = document.getElementById("overviewConcernTeams");

const exportTeamOverviewBtn = document.getElementById("exportTeamOverviewBtn");
const printTeamOverviewBtn = document.getElementById("printTeamOverviewBtn");

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 loadTeamOverviewReport() {
  showLoader("Loading team overview report...");

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

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

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

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

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

    const accessiblePlayerIds = new Set(players.map((player) => player.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);
    });

    renderTeamOverviewReport();
  } catch (error) {
    console.error("Team overview report error:", error);

    if (teamOverviewList) {
      teamOverviewList.innerHTML = `
        <div class="app-card">
          <strong>Could not load team overview report.</strong>
          <p>${error.message}</p>
        </div>
      `;
    }

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

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

  players.forEach((player) => {
    if (!player.teamId) return;

    if (!map.has(player.teamId)) {
      map.set(player.teamId, []);
    }

    map.get(player.teamId).push(player);
  });

  return map;
}

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 getTeamRows() {
  const playersByTeamMap = buildPlayersByTeamMap();
  const teamSessionCountMap = buildTeamSessionCountMap();
  const playerAttendanceMap = buildPlayerAttendanceMap();
  const latestWellnessByPlayer = getLatestWellnessByPlayer();
  const activeInjuryPlayerSet = buildActiveInjuryPlayerSet();

  return teams.map((team) => {
    const teamPlayers = playersByTeamMap.get(team.id) || [];
    const totalPlayers = teamPlayers.length;
    const totalSessions = teamSessionCountMap.get(team.id) || 0;

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

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

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

      return sessionTotal > 0
        ? Math.round((presentCount / sessionTotal) * 100)
        : 0;
    });

    const wellnessScores = teamPlayers.map((player) => {
      const latestWellness = latestWellnessByPlayer.get(player.id);
      return calculateWellnessScore(latestWellness);
    });

    const activeInjuries = teamPlayers.filter((player) => {
      return activeInjuryPlayerSet.has(player.id);
    }).length;

    const metrics = {
      totalPlayers,
      averageAttendance: average(attendanceRates),
      averageWellness: average(wellnessScores),
      activeInjuries
    };

    return {
      team,
      metrics,
      status: getTeamStatus(metrics)
    };
  });
}

function renderTeamOverviewReport() {
  teamOverviewList.innerHTML = "";

  if (!teams.length) {
    teamOverviewList.innerHTML = `
      <div class="app-card">
        <strong>No teams found.</strong>
        <p>No teams are available for this report.</p>
      </div>
    `;

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

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

  const strongCount = rows.filter((row) => row.status.key === "strong").length;
  const monitorCount = rows.filter((row) => row.status.key === "monitor").length;
  const concernCount = rows.filter((row) => row.status.key === "concern").length;

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

    item.innerHTML = `
      <div>
        <h3>${row.team.name || "Unnamed Team"}</h3>
        <p>
          ${row.metrics.totalPlayers} players in squad
          <span class="record-separator">&bull;</span>
          ${row.team.ageGroup || "No age group"}
        </p>
      </div>

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

        <span>Players: ${row.metrics.totalPlayers}</span>
        <span>Attendance: ${row.metrics.averageAttendance}%</span>
        <span>Wellness: ${row.metrics.averageWellness}%</span>
        <span>Active Injuries: ${row.metrics.activeInjuries}</span>
      </div>
    `;

    teamOverviewList.appendChild(item);
  });

  updateStats(rows.length, strongCount, monitorCount, concernCount);
}

function updateStats(total, strong, monitor, concern) {
  overviewTotalTeams.textContent = total;
  overviewStrongTeams.textContent = strong;
  overviewMonitorTeams.textContent = monitor;
  overviewConcernTeams.textContent = concern;
}

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 average(values) {
  if (!values.length) return 0;

  const total = values.reduce((sum, value) => sum + value, 0);

  return Math.round(total / values.length);
}

function getTeamStatus(metrics) {
  if (
    metrics.activeInjuries >= 3 ||
    metrics.averageAttendance < 60 ||
    metrics.averageWellness < 45
  ) {
    return {
      key: "concern",
      label: "Concern",
      className: "readiness-danger"
    };
  }

  if (
    metrics.activeInjuries >= 1 ||
    metrics.averageAttendance < 80 ||
    metrics.averageWellness < 70
  ) {
    return {
      key: "monitor",
      label: "Monitor",
      className: "readiness-monitor"
    };
  }

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

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

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

  const csvRows = [
    [
      "Team",
      "Total Players",
      "Average Attendance",
      "Average Wellness",
      "Active Injuries",
      "Team Status"
    ]
  ];

  rows.forEach((row) => {
    csvRows.push([
      row.team.name || "Unnamed Team",
      row.metrics.totalPlayers,
      `${row.metrics.averageAttendance}%`,
      `${row.metrics.averageWellness}%`,
      row.metrics.activeInjuries,
      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-team-overview-report.csv";
  link.click();

  URL.revokeObjectURL(url);
}

exportTeamOverviewBtn?.addEventListener("click", exportTeamOverviewCsv);

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

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

  await loadTeamOverviewReport();
});