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,
  addDoc,
  query,
  where,
  doc,
  updateDoc,
  serverTimestamp,
  setDoc,
  deleteDoc
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const sessionSelectForm = document.getElementById("sessionSelectForm");
const trainingSessionSelect = document.getElementById("trainingSessionSelect");

const attendanceSessionTitle = document.getElementById("attendanceSessionTitle");
const attendanceSessionMeta = document.getElementById("attendanceSessionMeta");
const attendanceTotalPlayers = document.getElementById("attendanceTotalPlayers");
const attendancePresentPlayers = document.getElementById("attendancePresentPlayers");
const attendancePercentage = document.getElementById("attendancePercentage");

const trainingAttendanceList = document.getElementById("trainingAttendanceList");
const saveTrainingAttendanceBtn = document.getElementById("saveTrainingAttendanceBtn");

let activeProfile = null;
let sessionsCache = [];
let playersCache = [];
let attendanceCache = [];
let selectedSession = null;

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

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

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

function getPlayerTeamIds(player) {
  if (!player) return [];

  const teamIds = Array.isArray(player.teamIds)
    ? [...player.teamIds]
    : [];

  if (player.teamId && !teamIds.includes(player.teamId)) {
    teamIds.push(player.teamId);
  }

  return teamIds.filter(Boolean);
}

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

function sortSessions() {
  sessionsCache.sort((a, b) => {
    return new Date(b.date || "1900-01-01") - new Date(a.date || "1900-01-01");
  });
}

function getStatusClass(status) {
  if (status === "present") return "readiness-ready";
  if (status === "late") return "readiness-monitor";
  if (status === "absent") return "readiness-danger";
  if (status === "injured") return "readiness-danger";

  return "readiness-monitor";
}

async function createTrainingAttendanceNotification(attendanceId, attendanceData) {
  const status = String(attendanceData.status || "").toLowerCase();
  const notificationRef = doc(db, "notifications", `training-attendance-${attendanceId}`);

  if (status === "present") {
    await deleteDoc(notificationRef).catch(() => {});
    return;
  }

  const isAbsent = status === "absent";
  const isLate = status === "late";
  const isInjured = status === "injured";

  await setDoc(notificationRef, {
    sourceId: attendanceId,
    sourceCollection: "trainingAttendance",
    type: "attendance",
    severity: isAbsent || isInjured ? "monitor" : "info",
    title: isAbsent
      ? "Training Attendance Missed"
      : isLate
        ? "Training Attendance Late"
        : isInjured
          ? "Training Injury Flag"
          : "Training Attendance Alert",
    message: `${attendanceData.playerName || "Player"} was marked as ${attendanceData.status || "not present"} for ${attendanceData.sessionType || "training"} on ${attendanceData.sessionDate || "No date"}.`,
    link: "attendance.html",
    playerId: attendanceData.playerId || "",
    playerName: attendanceData.playerName || "",
    teamId: attendanceData.teamId || "",
    teamName: attendanceData.teamName || "",
    organisationId: activeProfile.organisationId,
    readBy: {},
    createdAt: serverTimestamp(),
    updatedAt: serverTimestamp()
  });
}

async function loadTrainingSessions() {
  const q = query(
    collection(db, "trainingSessions"),
    where("organisationId", "==", activeProfile.organisationId)
  );

  const snapshot = await getDocs(q);

  sessionsCache = snapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((session) => canAccessTeam(session.teamId));

  sortSessions();

  trainingSessionSelect.innerHTML = `<option value="">Select training session</option>`;

  sessionsCache.forEach((session) => {
    const option = document.createElement("option");

    option.value = session.id;
    option.textContent = `${session.teamName || "Team"} • ${session.date || "No date"} • ${session.type || "training"}`;

    trainingSessionSelect.appendChild(option);
  });
}

async function loadSessionRegisterData() {
  if (!selectedSession) return;

  trainingAttendanceList.innerHTML = `
    <div class="app-card">
      Loading attendance register...
    </div>
  `;

  const playersQuery = query(
    collection(db, "players"),
    where("organisationId", "==", activeProfile.organisationId)
  );

  const attendanceQuery = query(
    collection(db, "trainingAttendance"),
    where("trainingSessionId", "==", selectedSession.id),
    where("organisationId", "==", activeProfile.organisationId)
  );

  const [playersSnapshot, attendanceSnapshot] = await Promise.all([
    getDocs(playersQuery),
    getDocs(attendanceQuery)
  ]);

  playersCache = playersSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((player) => {
      return getPlayerTeamIds(player).includes(selectedSession.teamId);
    });

  attendanceCache = attendanceSnapshot.docs.map((docSnap) => ({
    id: docSnap.id,
    ...docSnap.data()
  }));

  sortPlayers();
}

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

  attendanceCache.forEach((record) => {
    if (record.playerId) {
      map.set(record.playerId, record);
    }
  });

  return map;
}

function updateStats() {
  const rows = document.querySelectorAll(".training-attendance-status");

  const total = rows.length;

  const present = Array.from(rows).filter((select) => {
    return select.value === "present";
  }).length;

  const percentage = total ? Math.round((present / total) * 100) : 0;

  attendanceTotalPlayers.textContent = total;
  attendancePresentPlayers.textContent = present;
  attendancePercentage.textContent = `${percentage}%`;
}

function renderRegister() {
  if (!selectedSession) return;

  const attendanceMap = buildAttendanceMap();

  attendanceSessionTitle.textContent = selectedSession.teamName || "Training";

  attendanceSessionMeta.textContent = `
    ${selectedSession.date || "No date"}
    •
    ${selectedSession.time || "No time"}
    •
    ${selectedSession.type || "training"}
  `;

  trainingAttendanceList.innerHTML = "";

  if (!playersCache.length) {
    trainingAttendanceList.innerHTML = `
      <div class="app-card">
        No players found for this team.
      </div>
    `;

    updateStats();
    return;
  }

  playersCache.forEach((player) => {
    const existingRecord = attendanceMap.get(player.id);
    const status = existingRecord?.status || "present";

    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 ${getStatusClass(status)}">
          ${status}
        </span>

        <select
          class="training-attendance-status"
          data-player="${player.id}"
          data-record="${existingRecord?.id || ""}"
        >
          <option value="present" ${status === "present" ? "selected" : ""}>Present</option>
          <option value="absent" ${status === "absent" ? "selected" : ""}>Absent</option>
          <option value="late" ${status === "late" ? "selected" : ""}>Late</option>
          <option value="injured" ${status === "injured" ? "selected" : ""}>Injured</option>
        </select>
      </div>
    `;

    trainingAttendanceList.appendChild(item);
  });

  updateStats();
}

async function selectSession(sessionId) {
  selectedSession = sessionsCache.find((session) => session.id === sessionId);

  if (!selectedSession) {
    showToast("Please select a training session.", "warning");
    return;
  }

  await loadSessionRegisterData();
  renderRegister();
}

sessionSelectForm?.addEventListener("submit", async function (event) {
  event.preventDefault();

  const sessionId = trainingSessionSelect.value;
  await selectSession(sessionId);
});

trainingAttendanceList?.addEventListener("change", function (event) {
  if (!event.target.classList.contains("training-attendance-status")) return;

  const select = event.target;
  const row = select.closest(".elite-readiness-row");
  const pill = row?.querySelector(".report-pill");

  if (pill) {
    pill.textContent = select.value;
    pill.className = `report-pill ${getStatusClass(select.value)}`;
  }

  updateStats();
});

saveTrainingAttendanceBtn?.addEventListener("click", async function () {
  if (!selectedSession) {
    showToast("Please select a training session first.", "warning");
    return;
  }

  const rows = Array.from(
    document.querySelectorAll(".training-attendance-status")
  );

  if (!rows.length) {
    showToast("No players found to save.", "warning");
    return;
  }

  saveTrainingAttendanceBtn.disabled = true;
  saveTrainingAttendanceBtn.textContent = "Saving...";

  try {
    const saveOperations = rows.map(async (row) => {
      const playerId = row.dataset.player;
      const recordId = row.dataset.record;
      const status = row.value;

      const player = playersCache.find((item) => item.id === playerId);

      const attendanceData = {
        trainingSessionId: selectedSession.id,
        teamId: selectedSession.teamId,
        teamIds: getPlayerTeamIds(player),
        teamName: selectedSession.teamName || "",
        teamNames: player?.teamNames?.length
          ? player.teamNames
          : [selectedSession.teamName || ""],
        sessionDate: selectedSession.date || "",
        sessionType: selectedSession.type || "",
        playerId,
        playerName: getPlayerName(player),
        status,
        organisationId: activeProfile.organisationId,
        updatedAt: serverTimestamp()
      };

      if (recordId) {
        await updateDoc(doc(db, "trainingAttendance", recordId), attendanceData);
        await createTrainingAttendanceNotification(recordId, attendanceData);

        return {
          id: recordId,
          ...attendanceData,
          updatedAt: new Date()
        };
      }

      const newRef = await addDoc(collection(db, "trainingAttendance"), {
        ...attendanceData,
        createdBy: activeProfile.uid,
        createdAt: serverTimestamp()
      });

      await createTrainingAttendanceNotification(newRef.id, attendanceData);

      row.dataset.record = newRef.id;

      return {
        id: newRef.id,
        ...attendanceData,
        createdBy: activeProfile.uid,
        createdAt: new Date()
      };
    });

    attendanceCache = await Promise.all(saveOperations);

    showToast("Training attendance saved successfully.", "success");
    renderRegister();
  } catch (error) {
    console.error("Training attendance save error:", error);
    showToast("Could not save training attendance: " + error.message, "error");
  } finally {
    saveTrainingAttendanceBtn.disabled = false;
    saveTrainingAttendanceBtn.textContent = "Save Attendance";
  }
});

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

  showLoader("Loading training attendance...");

  try {
    await loadTrainingSessions();

    if (sessionIdFromUrl) {
      trainingSessionSelect.value = sessionIdFromUrl;

      if (trainingSessionSelect.value) {
        await selectSession(sessionIdFromUrl);
      }
    }
  } catch (error) {
    console.error("Training attendance load error:", error);

    trainingAttendanceList.innerHTML = `
      <div class="app-card">
        Error loading training attendance: ${error.message}
      </div>
    `;

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