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

const wellnessForm = document.getElementById("wellnessForm");
const wellnessList = document.getElementById("wellnessList");
const wellnessPlayer = document.getElementById("wellnessPlayer");
const sleepInput = document.getElementById("sleep");
const fatigueInput = document.getElementById("fatigue");
const sorenessInput = document.getElementById("soreness");
const wellnessTeamFilter = document.getElementById("wellnessTeamFilter");

let activeProfile = null;
let playersCache = [];
let teamsCache = [];
let wellnessCache = [];
let editingWellnessId = null;

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

function setSubmitLoading(isLoading) {
  if (!submitButton) return;

  submitButton.disabled = isLoading;
  submitButton.textContent = isLoading
    ? "Saving..."
    : editingWellnessId
      ? "Update Wellness"
      : "Save Wellness";
}

function getTeamName(teamId) {
  const team = teamsCache.find((item) => item.id === teamId);
  return team ? team.name || team.teamName || team.title || "Unnamed Team" : "No team assigned";
}

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 getPlayerTeamNames(player) {
  if (Array.isArray(player.teamNames) && player.teamNames.length) {
    return player.teamNames;
  }

  return getPlayerTeamIds(player).map((teamId) => getTeamName(teamId));
}

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

function resetFormMode() {
  editingWellnessId = null;

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

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

function canAccessTeam(teamId) {
  const role = activeProfile.role;
  const assignedTeamIds = activeProfile.assignedTeamIds || [];

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

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

  return false;
}

function canAccessPlayer(player) {
  const role = activeProfile.role;
  const assignedTeamIds = activeProfile.assignedTeamIds || [];
  const assignedPlayerIds = activeProfile.assignedPlayerIds || [];
  const playerTeamIds = getPlayerTeamIds(player);

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

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

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

  return false;
}

function canAccessWellness(record) {
  if (!activeProfile || !record) return false;

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

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

  if (role === "coach" || role === "biokineticist") {
    return (
      assignedTeamIds.includes(record.teamId) ||
      assignedPlayerIds.includes(record.playerId)
    );
  }

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

  return 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 sortWellnessCache() {
  wellnessCache.sort((a, b) => getDateValue(b) - getDateValue(a));
}

function getWellnessStatus(record) {
  const sleep = Number(record.sleep || 0);
  const fatigue = Number(record.fatigue || 0);
  const soreness = Number(record.soreness || 0);

  const riskCount =
    (sleep <= 2 ? 1 : 0) +
    (fatigue >= 4 ? 1 : 0) +
    (soreness >= 4 ? 1 : 0);

  if (riskCount >= 2) {
    return {
      label: "Wellness Needs Attention",
      className: "readiness-danger"
    };
  }

  if (riskCount === 1) {
    return {
      label: "Monitor",
      className: "readiness-monitor"
    };
  }

  return {
    label: "Ready",
    className: "readiness-ready"
  };
}

async function createWellnessNotification(wellnessId, wellnessData) {
  const sleep = Number(wellnessData.sleep || 0);
  const fatigue = Number(wellnessData.fatigue || 0);
  const soreness = Number(wellnessData.soreness || 0);

  const riskCount =
    (sleep <= 2 ? 1 : 0) +
    (fatigue >= 4 ? 1 : 0) +
    (soreness >= 4 ? 1 : 0);

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

  if (riskCount === 0) {
    await deleteDoc(notificationRef).catch(() => {});
    return;
  }

  await setDoc(notificationRef, {
    sourceId: wellnessId,
    sourceCollection: "wellness",
    type: "wellness",
    severity: riskCount >= 2 ? "danger" : "warning",
    title: `${wellnessData.playerName || "Player"} wellness risk`,
    message: `Wellness risk detected. Sleep: ${sleep}/5, Fatigue: ${fatigue}/5, Soreness: ${soreness}/5.`,
    link: "wellness.html",
    playerId: wellnessData.playerId || "",
    playerName: wellnessData.playerName || "",
    teamId: wellnessData.teamId || "",
    teamName: wellnessData.teamName || "",
    organisationId: activeProfile.organisationId,
    readBy: {},
    createdAt: serverTimestamp(),
    updatedAt: serverTimestamp()
  });
}

async function clearWellnessReminderNotification(playerId) {
  const todayKey = new Date().toISOString().slice(0, 10);

  await deleteDoc(
    doc(db, "notifications", `wellness-reminder-${playerId}-${todayKey}`)
  ).catch(() => {});
}

async function loadPageData() {
  let teamsSnapshot = { docs: [] };
  let playersSnapshot = { docs: [] };
  let wellnessSnapshot = { docs: [] };

  if (activeProfile.role === "player") {
    let linkedPlayerDoc = null;

    if (activeProfile.playerId) {
      const playerSnap = await getDoc(doc(db, "players", activeProfile.playerId));

      if (playerSnap.exists()) {
        linkedPlayerDoc = playerSnap;
      }
    }

    if (!linkedPlayerDoc) {
      const playerQuery = query(
        collection(db, "players"),
        where("organisationId", "==", activeProfile.organisationId),
        where("userId", "==", activeProfile.uid)
      );

      playersSnapshot = await getDocs(playerQuery);
      linkedPlayerDoc = playersSnapshot.docs[0] || null;
    } else {
      playersSnapshot = {
        docs: [linkedPlayerDoc]
      };
    }

    if (linkedPlayerDoc) {
      const linkedPlayerData = linkedPlayerDoc.data();

      const linkedTeamIds = Array.isArray(linkedPlayerData.teamIds)
        ? linkedPlayerData.teamIds
        : linkedPlayerData.teamId
        ? [linkedPlayerData.teamId]
        : [];

      const teamDocs = await Promise.all(
        linkedTeamIds.map((teamId) => getDoc(doc(db, "teams", teamId)))
      );

      teamsSnapshot = {
        docs: teamDocs.filter((teamSnap) => teamSnap.exists())
      };

      wellnessSnapshot = await getDocs(
        query(
          collection(db, "wellness"),
          where("organisationId", "==", activeProfile.organisationId),
          where("playerId", "==", linkedPlayerDoc.id)
        )
      );
    }
  } else {
    const teamsQuery = query(
      collection(db, "teams"),
      where("organisationId", "==", activeProfile.organisationId)
    );

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

    const wellnessQuery = query(
      collection(db, "wellness"),
      where("organisationId", "==", activeProfile.organisationId)
    );

    [teamsSnapshot, playersSnapshot, wellnessSnapshot] = await Promise.all([
      getDocs(teamsQuery),
      getDocs(playersQuery),
      getDocs(wellnessQuery)
    ]);
  }

  teamsCache = teamsSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((team) => canAccessTeam(team.id));

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

  wellnessCache = wellnessSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .filter((record) => canAccessWellness(record));

  sortWellnessCache();
}

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

  wellnessTeamFilter.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"}`;
    wellnessTeamFilter.appendChild(option);
  });
}

function setupPlayerWellnessMode() {
  if (activeProfile.role !== "player") return;

  const linkedPlayer = playersCache.find((player) => {
    return (
      player.userId === activeProfile.uid ||
      player.id === activeProfile.playerId
    );
  });

  if (!linkedPlayer) return;

  wellnessPlayer.value = linkedPlayer.id;
  wellnessPlayer.disabled = true;
}

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

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

  if (!playersCache.length) {
    wellnessPlayer.innerHTML = `<option value="">No players found</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);
    wellnessPlayer.appendChild(option);
  });
  
  setupPlayerWellnessMode();
}

function renderWellness() {
  if (!wellnessList) return;

  wellnessList.innerHTML = "";

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

  const filteredWellness = wellnessCache.filter((record) => {
    return (
      selectedTeamFilter === "all" ||
      record.teamId === selectedTeamFilter ||
      (Array.isArray(record.teamIds) && record.teamIds.includes(selectedTeamFilter))
    );
  });

  if (!filteredWellness.length) {
    wellnessList.innerHTML = `<div class="app-card">No wellness records yet.</div>`;
    return;
  }

  filteredWellness.forEach((record) => {
    const totalScore =
      Number(record.sleep || 0) +
      (6 - Number(record.fatigue || 0)) +
      (6 - Number(record.soreness || 0));

    const status = getWellnessStatus(record);

    const item = document.createElement("div");
    item.className = "wellness-card elite-wellness-card";

    item.innerHTML = `
      <div class="elite-injury-header">
        <div class="elite-injury-player">
          <span class="section-eyebrow">Wellness Record</span>
          <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="report-pill ${status.className}">
          ${status.label}
        </span>
      </div>

      <div class="elite-injury-grid">
        <div class="elite-injury-stat">
          <span>Total Score</span>
          <strong>${totalScore}/15</strong>
        </div>

        <div class="elite-injury-stat">
          <span>Sleep</span>
          <strong>${record.sleep || "-"}/5</strong>
        </div>

        <div class="elite-injury-stat">
          <span>Fatigue</span>
          <strong>${record.fatigue || "-"}/5</strong>
        </div>

        <div class="elite-injury-stat">
          <span>Soreness</span>
          <strong>${record.soreness || "-"}/5</strong>
        </div>

        <div class="elite-injury-stat">
          <span>Player</span>
          <strong>${record.playerName || "Unknown"}</strong>
        </div>

        <div class="elite-injury-stat">
          <span>Team</span>
          <strong>${record.teamName || "No team"}</strong>
        </div>
      </div>

      <div class="elite-injury-footer">
        <div class="elite-injury-meta">
          Wellness risk based on sleep, fatigue and soreness
        </div>

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

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

    wellnessList.appendChild(item);
  });
}

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

  const playerId = wellnessPlayer.value;
  const sleep = sleepInput.value;
  const fatigue = fatigueInput.value;
  const soreness = sorenessInput.value;
  
  const scores = [Number(sleep), Number(fatigue), Number(soreness)];

  if (scores.some((score) => Number.isNaN(score) || score < 1 || score > 5)) {
    showToast("Sleep, fatigue and soreness must each be between 1 and 5.", "warning");
    return;
  }

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

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

  if (!canAccessPlayer(selectedPlayer)) {
    showToast("You do not have access to this player.", "error");
    return;
  }
  
  const playerTeamIds = getPlayerTeamIds(selectedPlayer);
  const primaryTeamId =
    selectedPlayer.primaryTeamId ||
    selectedPlayer.teamId ||
    playerTeamIds[0] ||
    "";

  const primaryTeamName = getTeamName(primaryTeamId);
  const playerTeamNames = getPlayerTeamNames(selectedPlayer);

  const wellnessData = {
    playerId,
    playerName: getPlayerName(selectedPlayer),
    teamId: primaryTeamId,
    teamIds: playerTeamIds,
    teamName: playerTeamNames.length ? playerTeamNames.join(", ") : "Unassigned",
    teamNames: playerTeamNames,
    sleep: Number(sleep),
    fatigue: Number(fatigue),
    soreness: Number(soreness),
    organisationId: activeProfile.organisationId,
    updatedAt: serverTimestamp()
  };

  setSubmitLoading(true);

  try {
    if (editingWellnessId) {
      await updateDoc(doc(db, "wellness", editingWellnessId), wellnessData);
      await createWellnessNotification(editingWellnessId, wellnessData);
      await clearWellnessReminderNotification(playerId);

      wellnessCache = wellnessCache.map((record) =>
        record.id === editingWellnessId
          ? {
              ...record,
              ...wellnessData,
              updatedAt: new Date()
            }
          : record
      );

      showToast("Wellness record updated successfully.", "success");
    } else {
      const wellnessRef = await addDoc(collection(db, "wellness"), {
        ...wellnessData,
        createdBy: activeProfile.uid,
        createdDate: new Date().toISOString().slice(0, 10),
        createdAt: serverTimestamp()
      });

      await createWellnessNotification(wellnessRef.id, wellnessData);
      await clearWellnessReminderNotification(playerId);

      wellnessCache.unshift({
        id: wellnessRef.id,
        ...wellnessData,
        createdBy: activeProfile.uid,
        createdDate: new Date().toISOString().slice(0, 10),
        createdAt: new Date()
      });

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

    sortWellnessCache();
    resetFormMode();
    renderWellness();

  } catch (error) {
    console.error("Error saving wellness:", error);
    showToast("Could not save wellness: " + error.message, "error");
  } finally {
    setSubmitLoading(false);

    if (activeProfile?.role === "player") {
      setupPlayerWellnessMode();
    }
  }
});

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

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

    if (!record) return;

    editingWellnessId = record.id;
    wellnessPlayer.value = record.playerId || "";
    sleepInput.value = record.sleep || "";
    fatigueInput.value = record.fatigue || "";
    sorenessInput.value = record.soreness || "";

    submitButton.textContent = "Update Wellness";

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

  if (deleteBtn) {
    const recordId = deleteBtn.dataset.id;

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

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

      wellnessCache = wellnessCache.filter((record) => record.id !== recordId);

      renderWellness();
      showToast("Wellness record deleted.", "success");

    } catch (error) {
      console.error("Error deleting wellness:", error);
      showToast("Could not delete wellness: " + error.message, "error");
    }
  }
});

wellnessTeamFilter?.addEventListener("change", renderWellness);

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

  showLoader("Loading wellness...");

  wellnessList.innerHTML = `<div class="app-card">Loading wellness records...</div>`;

  try {
    await loadPageData();
    renderTeamFilter();
    renderPlayerDropdown();
    renderWellness();
  } catch (error) {
    console.error("Error loading wellness:", error);

    wellnessList.innerHTML = `
      <div class="app-card">
        Error loading wellness records: ${error.message}
      </div>
    `;

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