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

const injuryForm = document.getElementById("injuryForm");
const injuryList = document.getElementById("injuryList");
const injuryPlayer = document.getElementById("injuryPlayer");
const injuryType = document.getElementById("injuryType");
const injurySeverity = document.getElementById("injurySeverity");
const injuryStatus = document.getElementById("injuryStatus");
const injuryTeamFilter = document.getElementById("injuryTeamFilter");

let activeProfile = null;
let playersCache = [];
let teamsCache = [];
let injuriesCache = [];
let editingInjuryId = null;
let allowedTeamIds = [];

const submitButton = injuryForm?.querySelector("button[type='submit']");

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

function getTeamName(teamId) {
  const team = teamsCache.find((item) => item.id === teamId);

  return team
    ? team.name || team.teamName || team.title || "Unnamed Team"
    : "Unassigned";
}

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

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

  return teamIds.filter(Boolean);
}

function getPlayerStatusFromInjury(status) {
  const playerStatusMap = {
    active: "injured",
    recovery: "rehab",
    cleared: "available"
  };

  return playerStatusMap[status] || "injured";
}

function setButtonLoading(isLoading, text = "Saving...") {
  if (!submitButton) return;

  submitButton.disabled = isLoading;
  submitButton.textContent = isLoading
    ? text
    : editingInjuryId
      ? "Update Injury"
      : "Save Injury";
}

function resetFormMode() {
  editingInjuryId = null;

  if (injuryForm) {
    injuryForm.reset();
  }

  if (submitButton) {
    submitButton.textContent = "Save Injury";
    submitButton.disabled = false;
  }
}

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

function canAccessTeam(teamId) {
  if (!activeProfile) return false;

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

  return allowedTeamIds.includes(teamId);
}

function canAccessPlayer(player) {
  if (!activeProfile || !player) return false;

  const assignedPlayerIds = activeProfile.assignedPlayerIds || [];
  const playerTeamIds = getPlayerTeamIds(player);

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

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

  if (activeProfile.role === "biokineticist") {
    return (
      playerTeamIds.some((teamId) => allowedTeamIds.includes(teamId)) ||
      assignedPlayerIds.includes(player.id)
    );
  }

  return playerTeamIds.some((teamId) => allowedTeamIds.includes(teamId));
}

function canAccessInjury(injury) {
  if (!activeProfile || !injury) return false;

  const assignedPlayerIds = activeProfile.assignedPlayerIds || [];

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

  if (activeProfile.role === "player") {
    return playersCache.some((player) => {
      return player.id === injury.playerId && player.userId === activeProfile.uid;
    });
  }

  const injuryTeamIds = Array.isArray(injury.teamIds)
    ? injury.teamIds
    : injury.teamId
      ? [injury.teamId]
      : [];

  if (activeProfile.role === "biokineticist") {
    return (
      injuryTeamIds.some((teamId) => allowedTeamIds.includes(teamId)) ||
      assignedPlayerIds.includes(injury.playerId)
    );
  }

  return injuryTeamIds.some((teamId) => allowedTeamIds.includes(teamId));
}

function sortInjuriesCache() {
  injuriesCache.sort((a, b) => getDateValue(b) - getDateValue(a));
}

async function createInjuryNotification(injuryId, injuryData) {
  const status = String(injuryData.status || "").toLowerCase();
  const severity = String(injuryData.severity || "").toLowerCase();

  const notificationRef = doc(db, "notifications", `injury-${injuryId}`);

  let notificationTitle = `${injuryData.playerName || "Player"} injury alert`;
  let notificationMessage = `${injuryData.type || "Injury"} recorded as ${injuryData.status || "active"} with ${injuryData.severity || "unknown"} severity.`;
  let notificationSeverity = "monitor";

  const isHighRisk =
    status === "active" ||
    severity === "serious" ||
    severity.includes("major") ||
    severity.includes("severe") ||
    severity.includes("high");

  if (isHighRisk) {
    notificationSeverity = "high";
  }

  if (status === "recovery") {
    notificationTitle = "Recovery Status Changed";
    notificationMessage = `${injuryData.playerName || "Player"} has moved into recovery / rehab for ${injuryData.type || "injury"}.`;
    notificationSeverity = "monitor";
  }

  if (status === "cleared") {
    notificationTitle = "Cleared to Play";
    notificationMessage = `${injuryData.playerName || "Player"} has been cleared from ${injuryData.type || "injury"} and is available again.`;
    notificationSeverity = "info";
  }

  await setDoc(notificationRef, {
    sourceId: injuryId,
    sourceCollection: "injuries",
    type: "injury",
    severity: notificationSeverity,
    title: notificationTitle,
    message: notificationMessage,
    link: "injuries.html",
    playerId: injuryData.playerId || "",
    playerName: injuryData.playerName || "",
    teamId: injuryData.teamId || "",
    teamName: injuryData.teamName || "",
    organisationId: activeProfile.organisationId,
    readBy: {},
    createdAt: serverTimestamp(),
    updatedAt: serverTimestamp()
  });
}

async function syncPlayerStatus(playerId, status) {
  if (!playerId) return;

  const newPlayerStatus = getPlayerStatusFromInjury(status);

  await updateDoc(doc(db, "players", playerId), {
    status: newPlayerStatus,
    updatedAt: serverTimestamp()
  });

  playersCache = playersCache.map((player) =>
    player.id === playerId
      ? {
          ...player,
          status: newPlayerStatus,
          updatedAt: new Date()
        }
      : player
  );
}

async function loadPageData() {
  const teamsQuery = query(
    collection(db, "teams"),
    where("organisationId", "==", activeProfile.organisationId)
  );

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

  const injuriesQuery = query(
    collection(db, "injuries"),
    where("organisationId", "==", activeProfile.organisationId)
  );

  const [teamsSnapshot, playersSnapshot, injuriesSnapshot] = await Promise.all([
    getDocs(teamsQuery),
    getDocs(playersQuery),
    getDocs(injuriesQuery)
  ]);

  allowedTeamIds = activeProfile.assignedTeamIds || [];

  teamsCache = teamsSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((team) => {
      if (activeProfile.role === "director") return true;
      return allowedTeamIds.includes(team.id);
    });

  if (activeProfile.role === "director") {
    allowedTeamIds = teamsCache.map((team) => team.id);
  }

  playersCache = playersSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((player) => canAccessPlayer(player));

  injuriesCache = injuriesSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((injury) => canAccessInjury(injury));

  sortInjuriesCache();
}

function renderTeamFilter() {
  if (!injuryTeamFilter) return;

  injuryTeamFilter.innerHTML = `<option value="all">All Teams</option>`;

  teamsCache.forEach((team) => {
    const option = document.createElement("option");
    option.value = team.id;
    option.textContent = `${team.name || "Unnamed Team"} • ${team.ageGroup || "No age group"}`;
    injuryTeamFilter.appendChild(option);
  });
}

function renderPlayerDropdown() {
  if (!injuryPlayer) return;

  injuryPlayer.innerHTML = `<option value="">Select player</option>`;

  if (!playersCache.length) {
    injuryPlayer.innerHTML = `<option value="">No players available</option>`;
    return;
  }

  const sortedPlayers = [...playersCache].sort((a, b) => {
    return getPlayerName(a).toLowerCase().localeCompare(getPlayerName(b).toLowerCase());
  });

  sortedPlayers.forEach((player) => {
    const option = document.createElement("option");
    option.value = player.id;
    option.textContent = `${getPlayerName(player)} • ${
      player.teamNames?.length
        ? player.teamNames.join(", ")
        : getTeamName(player.teamId)
    }`;
    injuryPlayer.appendChild(option);
  });
}

function getInjuryStatusClass(status) {
  const cleanStatus = String(status || "active").toLowerCase();

  if (cleanStatus === "cleared") return "injury-cleared";
  if (cleanStatus === "recovery") return "injury-recovery";
  return "injury-active";
}

function renderInjuries() {
  if (!injuryList || !injuryTeamFilter) return;

  injuryList.innerHTML = "";

  const selectedTeamFilter = injuryTeamFilter.value || "all";

  const filteredInjuries = injuriesCache.filter((record) => {
    const recordTeamIds = Array.isArray(record.teamIds)
      ? record.teamIds
      : record.teamId
        ? [record.teamId]
        : [];

    return selectedTeamFilter === "all" || recordTeamIds.includes(selectedTeamFilter);
  });

  if (!filteredInjuries.length) {
    injuryList.innerHTML = `
      <div class="app-card">
        <strong>No injury records yet.</strong>
        <p>No injuries have been logged yet.</p>
      </div>
    `;
    return;
  }

  filteredInjuries.forEach((record) => {
    const status = record.status || "active";
    const item = document.createElement("div");

    item.className = "injury-card elite-injury-card";
    
    const daysInjured = Math.max(
      0,
      Math.floor((new Date() - getDateValue(record)) / (1000 * 60 * 60 * 24))
    );

    item.innerHTML = `
      <div class="elite-injury-header">
        <div class="elite-injury-player">
          <h3>${record.playerName || "Unknown Player"}</h3>
          <p>
            ${record.teamName || "No team"}
            <span class="record-separator">&bull;</span>
            ${record.createdDate || "No date"}
          </p>
        </div>

        <span class="status-pill ${getInjuryStatusClass(status)}">
          ${status}
        </span>
      </div>

      <div class="elite-injury-grid">
        <div class="elite-injury-stat">
          <span>Injury Type</span>
          <strong>${record.type || "N/A"}</strong>
        </div>

        <div class="elite-injury-stat">
          <span>Severity</span>
          <strong>${record.severity || "N/A"}</strong>
        </div>

        <div class="elite-injury-stat">
          <span>Status</span>
          <strong>${status}</strong>
        </div>
        
        <div class="elite-injury-stat">
          <span>Days Injured</span>
          <strong>${daysInjured}</strong>
        </div>
      </div>

      <div class="elite-injury-footer">
        <div class="elite-injury-meta">
          ${
            status === "cleared"
              ? "Cleared for return to play"
              : status === "recovery"
                ? "Recovery / rehab monitoring active"
                : "Unavailable until reviewed"
          }
        </div>

        ${
          activeProfile.role === "player"
            ? ""
            : `
              <div class="record-actions">
                <button class="btn-secondary edit-injury-btn" data-id="${record.id}" type="button">
                  Edit
                </button>

                <button class="btn-danger delete-injury-btn" data-id="${record.id}" type="button">
                  Delete
                </button>
              </div>
            `
          }
      </div>
    `;

    injuryList.appendChild(item);
  });
}

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

  if (activeProfile.role === "player") {
    showToast("Players can view injuries but cannot edit them.", "warning");
    return;
  }

  const playerId = injuryPlayer?.value;
  const selectedPlayer = playersCache.find((player) => player.id === playerId);

  if (!selectedPlayer) {
    showToast("Please select a player.", "warning");
    return;
  }

  if (!injuryType?.value.trim()) {
    showToast("Please enter the injury type.", "warning");
    return;
  }

  if (!canAccessPlayer(selectedPlayer)) {
    showToast("You do not have access to this player.", "error");
    return;
  }

  const injuryData = {
    playerId,
    playerName: getPlayerName(selectedPlayer),
    teamId: selectedPlayer.primaryTeamId || selectedPlayer.teamId || getPlayerTeamIds(selectedPlayer)[0] || "",
    teamIds: getPlayerTeamIds(selectedPlayer),
    teamName: selectedPlayer.teamNames?.length
      ? selectedPlayer.teamNames.join(", ")
      : selectedPlayer.teamName || getTeamName(selectedPlayer.teamId),
    teamNames: selectedPlayer.teamNames || getPlayerTeamIds(selectedPlayer).map((teamId) => getTeamName(teamId)),
    type: injuryType.value.trim(),
    severity: injurySeverity?.value || "minor",
    status: injuryStatus?.value || "active",
    organisationId: activeProfile.organisationId,
    updatedAt: serverTimestamp()
  };

  setButtonLoading(true, editingInjuryId ? "Updating..." : "Saving...");

  try {
    if (editingInjuryId) {
      await updateDoc(doc(db, "injuries", editingInjuryId), injuryData);
      await createInjuryNotification(editingInjuryId, injuryData);
      await syncPlayerStatus(playerId, injuryData.status);

      injuriesCache = injuriesCache.map((injury) =>
        injury.id === editingInjuryId
          ? {
              ...injury,
              ...injuryData,
              updatedAt: new Date()
            }
          : injury
      );

      showToast("Injury record updated successfully.", "success");
    } else {
      const createdDate = new Date().toISOString().slice(0, 10);

      const injuryRef = await addDoc(collection(db, "injuries"), {
        ...injuryData,
        createdBy: activeProfile.uid,
        createdDate,
        createdAt: serverTimestamp()
      });

      await createInjuryNotification(injuryRef.id, injuryData);
      await syncPlayerStatus(playerId, injuryData.status);

      injuriesCache.unshift({
        id: injuryRef.id,
        ...injuryData,
        createdBy: activeProfile.uid,
        createdDate,
        createdAt: new Date()
      });

      showToast("Injury record saved successfully.", "success");
    }

    sortInjuriesCache();
    resetFormMode();
    renderInjuries();
  } catch (error) {
    console.error("Error saving injury:", error);
    showToast("Could not save injury: " + error.message, "error");
  } finally {
    setButtonLoading(false);
  }
});

injuryList?.addEventListener("click", async function (event) {
  const editBtn = event.target.closest(".edit-injury-btn");
  const deleteBtn = event.target.closest(".delete-injury-btn");

  if (editBtn) {
    const recordId = editBtn.dataset.id;
    const record = injuriesCache.find((item) => item.id === recordId);

    if (!record) return;

    editingInjuryId = record.id;

    if (injuryPlayer) injuryPlayer.value = record.playerId || "";
    if (injuryType) injuryType.value = record.type || "";
    if (injurySeverity) injurySeverity.value = record.severity || "minor";
    if (injuryStatus) injuryStatus.value = record.status || "active";
    if (submitButton) submitButton.textContent = "Update Injury";

    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  if (deleteBtn) {
    const recordId = deleteBtn.dataset.id;
    const record = injuriesCache.find((item) => item.id === recordId);

    const confirmed = confirm("Are you sure you want to delete this injury record?");
    if (!confirmed) return;

    deleteBtn.disabled = true;
    deleteBtn.textContent = "Deleting...";

    try {
      await deleteDoc(doc(db, "injuries", recordId));
      await deleteDoc(doc(db, "notifications", `injury-${recordId}`)).catch(() => {});

      injuriesCache = injuriesCache.filter((injury) => injury.id !== recordId);

      if (record?.playerId) {
        await updateDoc(doc(db, "players", record.playerId), {
          status: "available",
          updatedAt: serverTimestamp()
        });

        playersCache = playersCache.map((player) =>
          player.id === record.playerId
            ? {
                ...player,
                status: "available",
                updatedAt: new Date()
              }
            : player
        );
      }

      renderInjuries();
      showToast("Injury record deleted.", "success");
    } catch (error) {
      console.error("Error deleting injury:", error);
      showToast("Could not delete injury: " + error.message, "error");
    } finally {
      deleteBtn.disabled = false;
      deleteBtn.textContent = "Delete";
    }
  }
});

injuryTeamFilter?.addEventListener("change", renderInjuries);

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

  showLoader("Loading injuries...");

  if (injuryList) {
    injuryList.innerHTML = `<div class="app-card">Loading injury records...</div>`;
  }

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

    await loadPageData();
    renderTeamFilter();
    renderPlayerDropdown();
    renderInjuries();
    resetFormMode();
  } catch (error) {
    console.error("Error loading injuries:", error);

    if (injuryList) {
      injuryList.innerHTML = `
        <div class="app-card">
          <strong>Error loading injuries.</strong>
          <p>${error.message}</p>
        </div>
      `;
    }

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