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

const attendanceTotalPlayers = document.getElementById("attendanceTotalPlayers");
const attendanceHighPlayers = document.getElementById("attendanceHighPlayers");
const attendanceMonitorPlayers = document.getElementById("attendanceMonitorPlayers");
const attendanceLowPlayers = document.getElementById("attendanceLowPlayers");

const exportAttendanceBtn = document.getElementById("exportAttendanceBtn");
const printAttendanceBtn = document.getElementById("printAttendanceBtn");

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

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

async function loadAttendanceReport() {
  showLoader("Loading attendance report...");

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

  try {
    const [
      playersRecords,
      teamsRecords,
      sessionRecords,
      generalAttendance,
      trainingAttendance
    ] = await Promise.all([
      getRecords("players"),
      getRecords("teams"),
      getRecords("trainingSessions"),
      getRecords("attendance"),
      getRecords("trainingAttendance")
    ]);

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

    players = playersRecords.filter((player) => 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) => accessibleTeamIds.has(session.teamId));

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

    populateTeamFilter();
    renderAttendanceReport();
  } catch (error) {
    console.error("Attendance report error:", error);

    attendanceReportList.innerHTML = `
      <div class="app-card">
        Could not load attendance report: ${error.message}
      </div>
    `;

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

function populateTeamFilter() {
  attendanceTeamFilter.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"}`;
    attendanceTeamFilter.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 getAttendanceRows(filteredPlayers) {
  const teamSessionCountMap = buildTeamSessionCountMap();
  const playerAttendanceMap = buildPlayerAttendanceMap();

  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 missedCount = Math.max(totalSessions - presentCount, 0);

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

    return {
      player,
      totalSessions,
      presentCount,
      missedCount,
      attendanceRate,
      status: getAttendanceStatus(attendanceRate)
    };
  });
}

function renderAttendanceReport() {
  const selectedTeam = attendanceTeamFilter.value || "all";

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

  attendanceReportList.innerHTML = "";

  if (!filteredPlayers.length) {
    attendanceReportList.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 = getAttendanceRows(filteredPlayers).sort((a, b) => {
    return b.attendanceRate - a.attendanceRate;
  });

  const highCount = rows.filter((row) => row.status.key === "high").length;
  const monitorCount = rows.filter((row) => row.status.key === "monitor").length;
  const lowCount = rows.filter((row) => row.status.key === "low").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>Present: ${row.presentCount}</span>
        <span>Missed: ${row.missedCount}</span>
        <span>Total Sessions: ${row.totalSessions}</span>
      </div>
    `;

    attendanceReportList.appendChild(item);
  });

  updateStats(rows.length, highCount, monitorCount, lowCount);
}

function updateStats(total, high, monitor, low) {
  attendanceTotalPlayers.textContent = total;
  attendanceHighPlayers.textContent = high;
  attendanceMonitorPlayers.textContent = monitor;
  attendanceLowPlayers.textContent = low;
}

function getAttendanceStatus(rate) {
  if (rate >= 85) {
    return {
      key: "high",
      label: "High",
      className: "readiness-ready"
    };
  }

  if (rate >= 65) {
    return {
      key: "monitor",
      label: "Monitor",
      className: "readiness-monitor"
    };
  }

  return {
    key: "low",
    label: "Low",
    className: "readiness-danger"
  };
}

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 exportAttendanceCsv() {
  const selectedTeam = attendanceTeamFilter.value || "all";

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

  const rows = getAttendanceRows(filteredPlayers);

  const csvRows = [
    ["Player", "Team", "Attendance %", "Status", "Present", "Missed", "Total Sessions"]
  ];

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

  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-attendance-report.csv";
  link.click();

  URL.revokeObjectURL(url);
}

attendanceTeamFilter?.addEventListener("change", renderAttendanceReport);

exportAttendanceBtn?.addEventListener("click", exportAttendanceCsv);

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

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