// =========================================================
// FILE: player-dashboard.js | TYPE: Elite Player Dashboard
// =========================================================

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

const playerStatus = document.getElementById("playerStatus");
const playerReadinessCard = document.getElementById("playerReadinessCard");
const playerStatusDescription = document.getElementById("playerStatusDescription");
const playerAttendance = document.getElementById("playerAttendance");
const playerWellness = document.getElementById("playerWellness");
const playerInjuries = document.getElementById("playerInjuries");

const playerWellnessList = document.getElementById("playerWellnessList");
const playerInjuryList = document.getElementById("playerInjuryList");
const playerUpcomingMatches = document.getElementById("playerUpcomingMatches");
const playerTrainingSchedule = document.getElementById("playerTrainingSchedule");
const playerAlertsList = document.getElementById("playerAlertsList");
const playerNotificationsList = document.getElementById("playerNotificationsList");
const heroPlayerReadiness = document.getElementById("heroPlayerReadiness");
const heroPlayerWellness = document.getElementById("heroPlayerWellness");
const heroPlayerAttendance = document.getElementById("heroPlayerAttendance");

const playerFocusTitle = document.getElementById("playerFocusTitle");
const playerFocusText = document.getElementById("playerFocusText");

const playerInsightsList = document.getElementById("playerInsightsList");
const playerHeroGreeting = document.getElementById("playerHeroGreeting");
const playerHeroSubtext = document.getElementById("playerHeroSubtext");

const playerNotificationCount = document.getElementById("playerNotificationCount");

let activeProfile = null;
let playerRecord = null;

let attendanceRecords = [];
let wellnessRecords = [];
let injuryRecords = [];
let matchRecords = [];
let trainingSessionRecords = [];
let notificationRecords = [];
let playerWellnessChartInstance = null;
let playerAttendanceChartInstance = null;
let playerReadinessChartInstance = null;

const CHART_THEME = {
  ready: "rgba(34,197,94,0.85)",
  warning: "rgba(245,158,11,0.85)",
  danger: "rgba(239,68,68,0.85)",
  primary: "rgba(56,189,248,0.85)",
  primarySoft: "rgba(56,189,248,0.16)",
  gameDay: "rgba(57,255,20,0.95)",
  gameDaySoft: "rgba(57,255,20,0.22)",
  text: "#ffffff",
  muted: "#cbd5e1",
  grid: "rgba(255,255,255,0.06)"
};

function getDateValue(record) {
  const dateValue =
    record?.date ||
    record?.sessionDate ||
    record?.createdDate;

  if (dateValue) {
    const dateString = String(dateValue);

    if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
      const [year, month, day] = dateString.split("-").map(Number);
      return new Date(year, month - 1, day);
    }

    return new Date(dateValue);
  }

  if (record?.createdAt?.toDate) return record.createdAt.toDate();
  if (record?.createdAt) return new Date(record.createdAt);

  return new Date(0);
}

function getDateLabel(record) {
  const date = getDateValue(record);

  if (!date || date.getTime() === 0) {
    return record?.createdDate || record?.date || "No date";
  }

  return date.toLocaleDateString("en-ZA", {
    year: "numeric",
    month: "short",
    day: "numeric"
  });
}

function getWeekdayIndex(record) {
  const date = getDateValue(record);

  if (!date || date.getTime() === 0) return -1;

  const day = date.getDay();

  return day === 0 ? 6 : day - 1;
}

function getCurrentWeekRecords(records) {
  const today = new Date();
  const day = today.getDay();
  const mondayOffset = day === 0 ? -6 : 1 - day;

  const monday = new Date(today);
  monday.setDate(today.getDate() + mondayOffset);
  monday.setHours(0, 0, 0, 0);

  const sunday = new Date(monday);
  sunday.setDate(monday.getDate() + 6);
  sunday.setHours(23, 59, 59, 999);

  return records.filter((record) => {
    const date = getDateValue(record);
    return date >= monday && date <= sunday;
  });
}

function getCurrentWeekGameDayIndexes() {
  const indexes = new Set();

  getCurrentWeekRecords(matchRecords).forEach((match) => {
    const index = getWeekdayIndex(match);

    if (index >= 0) {
      indexes.add(index);
    }
  });

  return indexes;
}

function getBaseChartOptions(extraOptions = {}) {
  return {
    responsive: true,
    maintainAspectRatio: false,
    resizeDelay: 200,

    layout: {
      padding: {
        top: 8,
        right: 12,
        bottom: 4,
        left: 4
      }
    },

    plugins: {
      legend: false
    },

    scales: {
      x: {
        ticks: {
          color: CHART_THEME.muted,
          maxRotation: 0,
          autoSkip: true,
          maxTicksLimit: 4,
          font: {
            size: 11
          }
        },
        grid: {
          color: CHART_THEME.grid,
          drawBorder: false
        }
      },

      y: {
        ticks: {
          color: CHART_THEME.muted,
          maxTicksLimit: 5,
          font: {
            size: 11
          }
        },
        grid: {
          color: CHART_THEME.grid,
          drawBorder: false
        }
      }
    },

    ...extraOptions
  };
}

function isActiveInjury(record) {
  const status = String(record.status || "").toLowerCase();
  return status !== "cleared" && status !== "closed" && status !== "resolved";
}

function getWellnessScore(record) {
  if (!record) return 0;

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

  return sleep + (6 - fatigue) + (6 - soreness);
}

function animateCounter(element, targetValue, duration = 750) {

  if (!element) return;

  const numericTarget =
    Number(String(targetValue).replace(/[^0-9.-]/g, "")) || 0;

  const suffix =
    String(targetValue).replace(/[0-9.-]/g, "");

  const startValue =
    Number(String(element.textContent).replace(/[^0-9.-]/g, "")) || 0;

  const startTime = performance.now();

  function updateCounter(currentTime) {

    const elapsed = currentTime - startTime;

    const progress = Math.min(elapsed / duration, 1);

    const currentValue = Math.floor(
      progress * (numericTarget - startValue) + startValue
    );

    element.textContent = `${currentValue}${suffix}`;

    if (progress < 1) {
      requestAnimationFrame(updateCounter);
    } else {
      element.textContent = targetValue;
    }
  }

  requestAnimationFrame(updateCounter);
}

function animateRing(selector, value) {

  const ring = document.querySelector(selector);

  if (!ring) return;

  const safeValue = Math.max(
    0,
    Math.min(100, Number(value) || 0)
  );

  requestAnimationFrame(() => {
    ring.style.setProperty("--value", `${safeValue}%`);
  });
}

function setText(element, value) {
  if (!element) return;
  element.textContent = value;
}

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

  if (cleanStatus === "cleared" || cleanStatus === "available") return "injury-cleared";
  if (cleanStatus === "recovery" || cleanStatus === "rehab") return "injury-recovery";

  return "injury-active";
}

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

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

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

  return teamIds.filter(Boolean);
}

async function loadPlayerRecord() {
  if (!activeProfile?.organisationId) {
    throw new Error("No organisation linked to this user.");
  }
  
  let snapshot = { empty: true, docs: [] };

  if (activeProfile.playerId) {
    const playerQueryById = query(
      collection(db, "players"),
      where("organisationId", "==", activeProfile.organisationId),
      where("__name__", "==", activeProfile.playerId)
    );

    snapshot = await getDocs(playerQueryById);
  }

  if (snapshot.empty) {
    const playersQuery = query(
      collection(db, "players"),
      where("organisationId", "==", activeProfile.organisationId),
      where("userId", "==", activeProfile.uid)
    );

    snapshot = await getDocs(playersQuery);
  }

  if (snapshot.empty) {
    setText(playerStatus, "No Profile");

    animateCounter(playerAttendance, "0%");
    animateCounter(heroPlayerAttendance, "0%");
    
    animateRing(".premium-attendance-ring", 0);
    
    animateCounter(heroPlayerReadiness, "0%");
    
    animateRing(".premium-ready-ring", 0);
    
    animateRing(".premium-danger-ring", 0);
    
    animateCounter(playerWellness, "0%");
    animateCounter(heroPlayerWellness, "0%");
    
    animateRing(".premium-wellness-ring", 0);
    
    setText(playerInjuries, "0");

    const message = `
      <div class="list-item">
        <strong>No player profile linked.</strong>
        <p>Please ask your coach or director to link your account to a player profile.</p>
      </div>
    `;

    if (playerWellnessList) playerWellnessList.innerHTML = message;
    if (playerInjuryList) playerInjuryList.innerHTML = message;
    if (playerAlertsList) playerAlertsList.innerHTML = message;
    
    if (playerNotificationsList) {
      playerNotificationsList.innerHTML = message;
    }
    
    if (playerUpcomingMatches) {
      playerUpcomingMatches.innerHTML = message;
    }
    
    if (playerTrainingSchedule) {
      playerTrainingSchedule.innerHTML = message;
    }
    
    if (playerInsightsList) {
      playerInsightsList.innerHTML = message;
    }

    return false;
  }

  const docSnap = snapshot.docs[0];

  playerRecord = {
    id: docSnap.id,
    ...docSnap.data()
  };
  
  if (playerHeroGreeting) {
    const playerName = `${playerRecord.firstName || ""} ${playerRecord.lastName || ""}`.trim();

    playerHeroGreeting.textContent =
      `Welcome Back, ${playerName || "Player"}`;
    }

    if (playerHeroSubtext) {
      playerHeroSubtext.textContent = `
        ${playerRecord.position || "Player"} •
        ${playerRecord.ageGroup || "No group"} •
        ${
          playerRecord.teamNames?.length
            ? playerRecord.teamNames.join(", ")
            : playerRecord.teamName || "Team"
        }
      `;
    }

  return true;
}

function mergeDocsToRecords(snapshotGroups) {
  const recordMap = new Map();

  snapshotGroups.forEach((snapshot) => {
    if (!snapshot?.docs) return;

    snapshot.docs.forEach((docSnap) => {
      recordMap.set(docSnap.id, {
        id: docSnap.id,
        ...docSnap.data()
      });
    });
  });

  return Array.from(recordMap.values());
}

async function loadPlayerData() {
  if (!activeProfile?.organisationId) {
    throw new Error("No organisation linked to this user.");
  }

  if (!playerRecord?.id) {
    throw new Error("No player profile linked.");
  }
  
  const attendanceQuery = query(
    collection(db, "attendance"),
    where("organisationId", "==", activeProfile.organisationId),
    where("playerId", "==", playerRecord.id)
  );

  const trainingAttendanceQuery = query(
    collection(db, "trainingAttendance"),
    where("organisationId", "==", activeProfile.organisationId),
    where("playerId", "==", playerRecord.id)
  );

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

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

  const playerTeamIds = getPlayerTeamIds();

  const matchQueries = playerTeamIds.slice(0, 10).map((teamId) =>
    getDocs(
      query(
        collection(db, "matches"),
        where("organisationId", "==", activeProfile.organisationId),
        where("teamId", "==", teamId)
      )
    )
  );
  
  const trainingSessionQueries = playerTeamIds.slice(0, 10).map((teamId) =>
    getDocs(
      query(
        collection(db, "trainingSessions"),
        where("organisationId", "==", activeProfile.organisationId),
        where("teamId", "==", teamId)
      )
    )
  );

  const notificationQueries = [];

  notificationQueries.push(
    getDocs(
      query(
        collection(db, "notifications"),
        where("organisationId", "==", activeProfile.organisationId),
        where("userId", "==", activeProfile.uid)
      )
    )
  );

  if (playerRecord?.id) {
    notificationQueries.push(
      getDocs(
        query(
          collection(db, "notifications"),
          where("organisationId", "==", activeProfile.organisationId),
          where("playerId", "==", playerRecord.id)
        )
      )
    );
  }

  playerTeamIds.slice(0, 10).forEach((teamId) => {
    notificationQueries.push(
      getDocs(
        query(
          collection(db, "notifications"),
          where("organisationId", "==", activeProfile.organisationId),
          where("teamId", "==", teamId)
        )
      )
    );
  });

  const results = await Promise.allSettled([
    getDocs(attendanceQuery),
    getDocs(trainingAttendanceQuery),
    getDocs(wellnessQuery),
    getDocs(injuriesQuery),
    Promise.all(matchQueries),
    Promise.all(trainingSessionQueries),
    Promise.all(notificationQueries)
  ]);

  const labels = [
    "attendance",
    "trainingAttendance",
    "wellness",
    "injuries",
    "matches",
    "trainingSessions",
    "notifications"
  ];

  results.forEach((result, index) => {
    if (result.status === "rejected") {
      console.error(`Player dashboard permission failed on: ${labels[index]}`, result.reason);
    }
  });

  const [
    attendanceSnapshot,
    trainingAttendanceSnapshot,
    wellnessSnapshot,
    injuriesSnapshot,
    matchSnapshots,
    trainingSessionSnapshots,
    notificationSnapshots
  ] = results.map((result) =>
    result.status === "fulfilled" ? result.value : { docs: [] }
  );

  const matchesDocs = Array.isArray(matchSnapshots)
    ? matchSnapshots.flatMap((snapshot) => snapshot.docs)
    : [];
    
  const trainingSessionDocs = Array.isArray(trainingSessionSnapshots)
    ? trainingSessionSnapshots.flatMap((snapshot) => snapshot.docs)
    : [];

  attendanceRecords = [
    ...attendanceSnapshot.docs.map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    })),
    ...trainingAttendanceSnapshot.docs.map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
  ].sort((a, b) => getDateValue(b) - getDateValue(a));

  wellnessRecords = wellnessSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .sort((a, b) => getDateValue(b) - getDateValue(a));

  injuryRecords = injuriesSnapshot.docs
    .map((docSnap) => ({
      id: docSnap.id,
      ...docSnap.data()
    }))
    .sort((a, b) => getDateValue(b) - getDateValue(a));

  const uniqueMatches = new Map();

  matchesDocs.forEach((docSnap) => {
    uniqueMatches.set(docSnap.id, {
      id: docSnap.id,
      ...docSnap.data()
    });
  });

  matchRecords = Array.from(uniqueMatches.values())
    .sort((a, b) => {
      return new Date(a.date || "1900-01-01") - new Date(b.date || "1900-01-01");
    });
    
  const uniqueTrainingSessions = new Map();

  trainingSessionDocs.forEach((docSnap) => {
    uniqueTrainingSessions.set(docSnap.id, {
      id: docSnap.id,
      ...docSnap.data()
    });
  });

  trainingSessionRecords = Array.from(uniqueTrainingSessions.values())
    .sort((a, b) => {
      return new Date(a.date || "1900-01-01") - new Date(b.date || "1900-01-01");
    });

  notificationRecords = mergeDocsToRecords(
    Array.isArray(notificationSnapshots) ? notificationSnapshots : []
  ).sort((a, b) => getDateValue(b) - getDateValue(a));
}

function renderAttendance() {
  if (!attendanceRecords.length) {
    animateCounter(playerAttendance, "0%");
    animateCounter(heroPlayerAttendance, "0%");
    
    animateRing(".premium-attendance-ring", 0);
    
    return;
  }

  const present = attendanceRecords.filter((record) => record.status === "present").length;
  const percentage = Math.round((present / attendanceRecords.length) * 100);

  animateCounter(playerAttendance, `${percentage}%`);
  animateCounter(heroPlayerAttendance, `${percentage}%`);

  animateRing(".premium-attendance-ring", percentage);
}

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

  playerWellnessList.innerHTML = "";

  if (!wellnessRecords.length) {
    animateCounter(playerWellness, "0%");
    animateCounter(heroPlayerWellness, "0%");
    
    animateRing(".premium-wellness-ring", 0);

    playerWellnessList.innerHTML = `
      <div class="list-item">
        <strong>No wellness records yet.</strong>
        <p>Submit your first wellness check-in to activate readiness tracking.</p>
      </div>
    `;
    return;
  }

  const latest = wellnessRecords[0];
  const latestScore = getWellnessScore(latest);

  const wellnessPercent =
  Math.round((latestScore / 15) * 100);

  animateCounter(playerWellness, `${wellnessPercent}%`);
  animateCounter(heroPlayerWellness, `${wellnessPercent}%`);

  animateRing(".premium-wellness-ring", wellnessPercent);

  wellnessRecords.slice(0, 5).forEach((record) => {
    const score = getWellnessScore(record);

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

    item.innerHTML = `
      <div class="wellness-card-header">
        <div>
          <h3>${getDateLabel(record)}</h3>
          <p>Latest player wellness check-in</p>
        </div>

        <span class="wellness-score">${score}/15</span>
      </div>

      <div class="wellness-metrics">
        <div>
          <span>Sleep</span>
          <strong>${record.sleep || "-"}/5</strong>
        </div>

        <div>
          <span>Fatigue</span>
          <strong>${record.fatigue || "-"}/5</strong>
        </div>

        <div>
          <span>Soreness</span>
          <strong>${record.soreness || "-"}/5</strong>
        </div>
      </div>
    `;

    playerWellnessList.appendChild(item);
  });
}

function renderInjuries() {
  if (!playerInjuryList) return;

  const active = injuryRecords.filter((record) => isActiveInjury(record));

  animateCounter(playerInjuries, active.length);

  const injuryPercent =
    active.length > 0 ? 100 : 0;
 
  animateRing(".premium-danger-ring", injuryPercent);

  playerInjuryList.innerHTML = "";

  if (!injuryRecords.length) {
    playerInjuryList.innerHTML = `
      <div class="list-item">
        <strong>No injury history.</strong>
        <p>You currently have no injury records linked to your profile.</p>
      </div>
    `;
    return;
  }

  injuryRecords.slice(0, 5).forEach((record) => {
    const item = document.createElement("article");
    item.className = "elite-injury-card";

    item.innerHTML = `
      <div class="elite-injury-header">
        <div class="elite-injury-player">
          <h3>${record.type || "Unknown Injury"}</h3>
          <p>${getDateLabel(record)}</p>
        </div>

        <span class="status-pill ${getStatusClass(record.status)}">
          ${record.status || "active"}
        </span>
      </div>

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

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

        <div class="elite-injury-stat">
          <span>RTP</span>
          <strong>${isActiveInjury(record) ? "Monitor" : "Cleared"}</strong>
        </div>
      </div>
    `;

    playerInjuryList.appendChild(item);
  });
}

function renderUpcomingMatches() {
  if (!playerUpcomingMatches) return;

  playerUpcomingMatches.innerHTML = "";

  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const upcomingMatches = matchRecords.filter((match) => {
    const matchDate = new Date(match.date || "1900-01-01");
    matchDate.setHours(0, 0, 0, 0);
    return matchDate >= today;
  });

  if (!upcomingMatches.length) {
    playerUpcomingMatches.innerHTML = `
      <div class="list-item">
        <strong>No upcoming matches.</strong>
        <p>Your upcoming fixtures will appear here once scheduled.</p>
      </div>
    `;
    return;
  }

  upcomingMatches.slice(0, 3).forEach((match) => {
    const item = document.createElement("article");
    item.className = "elite-player-card";

    item.innerHTML = `
      <h3>${match.teamName || "My Team"} vs ${match.opponent || "Opponent"}</h3>

      <p>
        ${match.date || "No date"}
        ${match.venue ? " • " + match.venue : ""}
        ${match.type ? " • " + match.type : ""}
      </p>

      <div class="record-actions">
        <a href="player-match-detail.html?id=${match.id}" class="btn-secondary">
          View Fixture
        </a>
      </div>
    `;

    playerUpcomingMatches.appendChild(item);
  });
}

function formatSessionType(type) {
  return String(type || "training")
    .replaceAll("_", " ")
    .replace(/\b\w/g, (char) => char.toUpperCase());
}

function renderTrainingSchedule() {
  if (!playerTrainingSchedule) return;

  playerTrainingSchedule.innerHTML = "";

  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const upcomingSessions = trainingSessionRecords.filter((session) => {
    const sessionDate = new Date(session.date || "1900-01-01");
    sessionDate.setHours(0, 0, 0, 0);
    return sessionDate >= today;
  });

  if (!upcomingSessions.length) {
    playerTrainingSchedule.innerHTML = `
      <div class="list-item">
        <strong>No upcoming training sessions.</strong>
        <p>Your training schedule will appear here once your coach adds sessions.</p>
      </div>
    `;
    return;
  }

  upcomingSessions.slice(0, 5).forEach((session) => {
    const item = document.createElement("article");
    item.className = "training-session-card";

    item.innerHTML = `
      <div class="training-session-header">
        <div>
          <span class="section-eyebrow">Training Session</span>
          <h3>${session.teamName || "Training Session"}</h3>
        </div>

        <span class="report-pill readiness-monitor">
          ${formatSessionType(session.type)}
        </span>
      </div>

      <div class="training-session-grid">
        <div>
          <span>Date</span>
          <strong>${session.date || "No date"}</strong>
        </div>

        <div>
          <span>Time</span>
          <strong>${session.time || "No time"}</strong>
        </div>

        <div>
          <span>Venue</span>
          <strong>${session.location || session.venue || "No venue"}</strong>
        </div>
      </div>
    `;

    playerTrainingSchedule.appendChild(item);
  });
}

function renderReadiness() {
  const activeInjuries = injuryRecords.filter((record) => isActiveInjury(record));
  const latestWellness = wellnessRecords[0];
  const wellnessScore = latestWellness ? getWellnessScore(latestWellness) : 0;

  let readiness = "READY";
  let description = "You are currently available for selection.";
  let cardClass = "stat-ready";

  if (activeInjuries.length > 0) {

    readiness = "UNAVAILABLE";

    description =
      "You have an active injury record. Follow your recovery plan.";

    cardClass = "stat-danger";

    setText(playerFocusTitle, "Recovery Required");

    setText(
      playerFocusText,
      "Follow your recovery plan and medical guidance before returning to play."
    );

  } else if (wellnessScore < 11) {

    readiness = "MONITOR";

    description =
      "Your wellness score indicates possible fatigue or soreness.";

    cardClass = "stat-warning";
  
    setText(playerFocusTitle, "Monitor Recovery");

    setText(
      playerFocusText,
      "Fatigue and soreness indicators suggest additional recovery is needed."
    );

  } else {

    setText(playerFocusTitle, "Match Ready");

    setText(
      playerFocusText,
      "Your wellness and readiness indicators are currently stable."
    ); 
  }

  const readinessPercent =
    readiness === "READY"
      ? 100
      : readiness === "MONITOR"
      ? 60
      : 25;

  animateCounter(
    heroPlayerReadiness,
    `${readinessPercent}%`
  );

  animateCounter(
    playerStatus,
    `${readinessPercent}%`
  );
  
  animateRing(
    ".premium-ready-ring",
    readinessPercent 
  );

  setText(playerStatusDescription, description);
  
  if (playerReadinessCard) {

    playerReadinessCard.classList.remove(
      "stat-ready",
      "stat-warning",
      "stat-danger"
    );

    playerReadinessCard.classList.add(cardClass);
  }
}

function isTodayDate(record) {
  const date = getDateValue(record);
  const today = new Date();

  return (
    date.getFullYear() === today.getFullYear() &&
    date.getMonth() === today.getMonth() &&
    date.getDate() === today.getDate()
  );
}

function getDaysUntil(dateValue) {
  if (!dateValue) return null;

  const today = new Date();
  const targetDate = new Date(dateValue);

  today.setHours(0, 0, 0, 0);
  targetDate.setHours(0, 0, 0, 0);

  return Math.ceil(
    (targetDate - today) / (1000 * 60 * 60 * 24)
  );
}

async function createWellnessReminderNotification() {
  if (!activeProfile?.organisationId || !playerRecord?.id) return;

  const hasWellnessToday = wellnessRecords.some((record) =>
    isTodayDate(record)
  );

  if (hasWellnessToday) return;

  const upcomingMatch = matchRecords.find((match) => {
    const daysUntil = getDaysUntil(match.date);
    return daysUntil === 0 || daysUntil === 1;
  });

  const title = upcomingMatch
    ? "Wellness Required Before Match"
    : "Submit Wellness Today";

  const message = upcomingMatch
    ? `Please submit your wellness check-in before ${upcomingMatch.teamName || "your team"} vs ${upcomingMatch.opponent || "Opponent"}.`
    : "Please submit your wellness check-in today to keep your readiness profile updated.";

  const notificationRef = doc(
    db,
    "notifications",
    `wellness-reminder-${playerRecord.id}-${new Date().toISOString().slice(0, 10)}`
  );

  await setDoc(notificationRef, {
    sourceId: playerRecord.id,
    sourceCollection: "players",
    type: "wellness",
    severity: upcomingMatch ? "monitor" : "info",
    title,
    message,
    link: "wellness.html",
    userId: activeProfile.uid || "",
    playerId: playerRecord.id || "",
    playerName: `${playerRecord.firstName || ""} ${playerRecord.lastName || ""}`.trim(),
    teamId: playerRecord.primaryTeamId || playerRecord.teamId || "",
    teamName: playerRecord.teamName || "",
    organisationId: activeProfile.organisationId,
    readBy: {},
    createdAt: serverTimestamp(),
    updatedAt: serverTimestamp()
  });
}

function renderPlayerAlerts() {
  if (!playerAlertsList) return;

  playerAlertsList.innerHTML = "";

  const alerts = [];

  const activeInjuries = injuryRecords.filter((record) => isActiveInjury(record));
  const latestWellness = wellnessRecords[0];
  const wellnessScore = latestWellness ? getWellnessScore(latestWellness) : 0;

  if (!wellnessRecords.length) {
    alerts.push({
      title: "Submit wellness check-in",
      text: "No wellness check-in has been recorded yet.",
      action: "Submit Wellness",
      link: "wellness.html",
      severity: "warning"
    });
  }

  if (activeInjuries.length > 0) {
    alerts.push({
      title: "Active injury record",
      text: "You currently have an active injury. Follow your recovery plan before returning to play.",
      action: "View Injuries",
      link: "injuries.html",
      severity: "danger"
    });
  }

  if (wellnessScore < 11) {
    alerts.push({
      title: "Wellness needs attention",
      text: "Your latest wellness score is high. Recovery, fatigue or soreness should be monitored.",
      action: "Update Wellness",
      link: "wellness.html",
      severity: "warning"
    });
  }

  if (!alerts.length) {
    playerAlertsList.innerHTML = `
      <div class="list-item">
        <strong>No action required.</strong>
        <p>Your profile is currently stable.</p>
      </div>
    `;
    return;
  }

  alerts.forEach((alert) => {
    const item = document.createElement("article");
    item.className = `elite-player-card notification-${alert.severity || "info"}`;

    item.innerHTML = `
      <h3>${alert.title}</h3>
      <p>${alert.text}</p>

      <div class="record-actions">
        <a href="${alert.link}" class="btn-primary">
          ${alert.action}
        </a>
      </div>
    `;

    playerAlertsList.appendChild(item);
  });
}

function isPlayerNotificationRead(notification) {
  if (!notification || !activeProfile?.uid) return false;

  return Boolean(
    notification.readBy &&
    notification.readBy[activeProfile.uid]
  );
}

function formatPlayerNotificationType(type) {
  const cleanType = String(type || "").toLowerCase();

  if (cleanType === "announcement") return "Coach Announcement";
  if (cleanType === "selection") return "Selection Update";
  if (cleanType === "match") return "Match Update";
  if (cleanType === "training") return "Training Update";
  if (cleanType === "load") return "Training Load";
  if (cleanType === "wellness") return "Wellness";
  if (cleanType === "attendance") return "Attendance";
  if (cleanType === "injury") return "Medical";
  if (cleanType === "dashboard_alert") return "Dashboard Alert";
  if (cleanType === "user") return "Account";

  return "Team Update";
}

function renderNotifications() {
  if (!playerNotificationsList) return;

  playerNotificationsList.innerHTML = "";
  
  const unreadCount =
    notificationRecords.filter(
      (notification) => !isPlayerNotificationRead(notification)
    ).length;

  if (playerNotificationCount) {
    playerNotificationCount.textContent = unreadCount;
  }

  if (!notificationRecords.length) {
    playerNotificationsList.innerHTML = `
      <div class="list-item">
        <strong>No notifications yet.</strong>
        <p>Your alerts and team updates will appear here.</p>
      </div>
    `;
    return;
  }

  notificationRecords
    .sort((a, b) => {
      const aUnread = !isPlayerNotificationRead(a);
      const bUnread = !isPlayerNotificationRead(b);

      if (aUnread && !bUnread) return -1;
      if (!aUnread && bUnread) return 1;

      return getDateValue(b) - getDateValue(a);
    })
    .slice(0, 5)
    .forEach((notification) => {
    const item = document.createElement("article");
    item.className = `
      notification-item
      elite-notification-card
      notification-${notification.severity || "info"}
      ${isPlayerNotificationRead(notification) ? "notification-read" : ""}
    `;

    item.innerHTML = `
      <div class="notification-content">
        <div class="notification-header">
          <div>
            <span class="elite-notification-type">
              ${formatPlayerNotificationType(notification.type)}
            </span>

            <h3>${notification.title || "Notification"}</h3>
          </div>

          <span class="status-pill ${isPlayerNotificationRead(notification) ? "" : "status-live"}">
            ${isPlayerNotificationRead(notification) ? "Read" : "Unread"}
          </span>
        </div>

        <p>${notification.message || ""}</p>

        <small class="small-text">
          ${getDateLabel(notification)}
        </small>

        <div class="record-actions">
          ${
            notification.link
              ? `<a href="${notification.link}" class="btn-secondary">Open</a>`
              : ""
          }

          ${
            isPlayerNotificationRead(notification)
              ? ""
              : `
                <button
                  class="btn-primary mark-notification-read-btn"
                  data-id="${notification.id}"
                  type="button"
                >
                  Mark Read
                </button>
              `
          }
        </div>
      </div>
    `;

    playerNotificationsList.appendChild(item);
  });
}

function setupNotificationActions() {
  const buttons = document.querySelectorAll(".mark-notification-read-btn");

  buttons.forEach((button) => {
    button.addEventListener("click", async () => {
      const notificationId = button.dataset.id;

      if (!notificationId) return;

      try {
        button.disabled = true;
        button.textContent = "Updating...";

        await updateDoc(doc(db, "notifications", notificationId), {
          [`readBy.${activeProfile.uid}`]: true
        });

        showToast("Notification marked as read", "success");

        const notification = notificationRecords.find((item) => item.id === notificationId);

        if (notification) {
          notification.readBy = {
            ...(notification.readBy || {}),
            [activeProfile.uid]: true
          };
        }

        renderNotifications();
        setupNotificationActions();
      } catch (error) {
        console.error("Notification update error:", error);
        showToast("Could not update notification", "error");

        button.disabled = false;
        button.textContent = "Mark Read";
      }
    });
  });
}

function renderPlayerInsights() {

  if (!playerInsightsList) return;

  playerInsightsList.innerHTML = "";

  const insights = [];

  const activeInjuries =
    injuryRecords.filter((record) => isActiveInjury(record));

  const latestWellness = wellnessRecords[0];

  const wellnessScore =
    latestWellness
      ? getWellnessScore(latestWellness)
      : 0;

  if (activeInjuries.length > 0) {

    insights.push({
      type: "danger",
      title: "Recovery Required",
      text: "You currently have an active injury requiring recovery monitoring."
    });
  }

  if (wellnessScore > 0 && wellnessScore < 11) {

    insights.push({
      type: "warning",
      title: "Elevated Fatigue",
      text: "Your latest wellness score suggests fatigue, soreness or recovery concerns."
    });
  }

  if (attendanceRecords.length > 0) {

    const present =
      attendanceRecords.filter(
        (record) => record.status === "present"
      ).length;

    const attendancePercent =
      Math.round((present / attendanceRecords.length) * 100);

    if (attendancePercent < 75) {

      insights.push({
        type: "warning",
        title: "Attendance Risk",
        text: `Your attendance is currently ${attendancePercent}%.`
      });
    }
  }

  if (!insights.length) {

    insights.push({
      type: "good",
      title: "Performance Stable",
      text: "Your readiness and wellness indicators are looking strong."
    });
  }

  insights.forEach((insight) => {

    const item = document.createElement("div");

    item.className = "insight-item";

    item.innerHTML = `
      <span class="insight-dot insight-${insight.type}"></span>

      <div>
        <strong>${insight.title}</strong>
        <p>${insight.text}</p>
      </div>
    `;

    playerInsightsList.appendChild(item);
  });
}

function renderWellnessChart() {
  if (typeof Chart === "undefined") return;

  const canvas = document.getElementById("playerWellnessChart");
  if (!canvas) return;

  if (playerWellnessChartInstance) {
    playerWellnessChartInstance.destroy();
  }

  const weekLabels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
  const weekData = [0, 0, 0, 0, 0, 0, 0];

  getCurrentWeekRecords(wellnessRecords).forEach((record) => {
    const index = getWeekdayIndex(record);
    if (index >= 0) {
      weekData[index] = Math.round((getWellnessScore(record) / 15) * 100);
    }
  });

  playerWellnessChartInstance = new Chart(canvas, {
    type: "line",
    data: {
      labels: weekLabels,
      datasets: [{
        label: "Wellness",
        data: weekData,
        borderColor: CHART_THEME.ready,
        backgroundColor: "rgba(34,197,94,0.16)",
        fill: true,
        tension: 0.35,
        borderWidth: 3,
        pointRadius: 5,
        pointHoverRadius: 6
      }]
    },
    options: getBaseChartOptions({
      scales: {
        y: {
          min: 0,
          max: 100,
          ticks: {
            color: CHART_THEME.muted,
            callback: (value) => `${value}%`
          },
          grid: {
            color: CHART_THEME.grid
          }
        },
        x: {
          ticks: {
            color: CHART_THEME.muted
          },
          grid: {
            display: false
          }
        }
      }
    })
  });
}



function renderReadinessChart() {
  if (typeof Chart === "undefined") return;

  const canvas = document.getElementById("playerReadinessChart");
  if (!canvas) return;

  if (playerReadinessChartInstance) {
    playerReadinessChartInstance.destroy();
  }

  const weekLabels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
  const weekData = [0, 0, 0, 0, 0, 0, 0];

  getCurrentWeekRecords(wellnessRecords).forEach((record) => {
    const index = getWeekdayIndex(record);
    if (index >= 0) {
      const score = getWellnessScore(record);
      weekData[index] = score < 11 ? 60 : 100;
    }
  });

  playerReadinessChartInstance = new Chart(canvas, {
    type: "line",
    data: {
      labels: weekLabels,
      datasets: [{
        label: "Readiness",
        data: weekData,
        borderColor: CHART_THEME.warning,
        backgroundColor: "rgba(245,158,11,0.12)",
        fill: true,
        tension: 0.35,
        borderWidth: 3,
        pointRadius: 5,
        pointHoverRadius: 6
      }]
    },
    options: getBaseChartOptions({
      scales: {
        y: {
          min: 0,
          max: 100,
          ticks: {
            color: CHART_THEME.muted,
            callback: (value) => `${value}%`
          },
          grid: {
            color: CHART_THEME.grid
          }
        },
        x: {
          ticks: {
            color: CHART_THEME.muted
          },
          grid: {
            display: false
          }
        }
      }
    })
  });
}

function renderAttendanceChart() {
  if (typeof Chart === "undefined") return;

  const canvas = document.getElementById("playerAttendanceChart");
  if (!canvas) return;

  if (playerAttendanceChartInstance) {
    playerAttendanceChartInstance.destroy();
  }

  const weekLabels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
  const totals = [0, 0, 0, 0, 0, 0, 0];
  const present = [0, 0, 0, 0, 0, 0, 0];

  getCurrentWeekRecords(attendanceRecords).forEach((record) => {
    const index = getWeekdayIndex(record);
    if (index < 0) return;

    totals[index]++;

    if (String(record.status || "").toLowerCase() === "present") {
      present[index]++;
    }
  });

  const weekData = totals.map((total, index) => {
    if (!total) return 0;
    return Math.round((present[index] / total) * 100);
  });

  const gameDayIndexes = getCurrentWeekGameDayIndexes();

  const barColors = weekData.map((value, index) => {
    if (gameDayIndexes.has(index)) {
      return CHART_THEME.gameDay;
    }

    return CHART_THEME.primary;
  });

  playerAttendanceChartInstance = new Chart(canvas, {
    type: "bar",
    data: {
      labels: weekLabels,
      datasets: [{
        label: "Attendance",
        data: weekData,
        backgroundColor: barColors,
        borderColor: barColors,
        borderWidth: 1,
        borderRadius: 8,
        barPercentage: 0.42,
        categoryPercentage: 0.65
      }]
    },
    options: getBaseChartOptions({
      plugins: {
        legend: false,
        tooltip: {
          callbacks: {
            label: function (context) {
              const index = context.dataIndex;
              const value = context.raw || 0;

              return gameDayIndexes.has(index)
                ? `Game Day • Attendance ${value}%`
                : `Attendance ${value}%`;
            }
          }
        }
      },
      scales: {
        y: {
          min: 0,
          max: 100,
          ticks: {
            color: CHART_THEME.muted,
            callback: (value) => `${value}%`
          },
          grid: {
            color: CHART_THEME.grid
          }
        },
        x: {
          ticks: {
            color: function (context) {
              return gameDayIndexes.has(context.index)
                ? CHART_THEME.gameDay
                : CHART_THEME.muted;
            }
          },
          grid: {
            display: false
          }
        }
      }
    })
  });
}

function renderDashboard() {
  renderAttendance();
  renderWellness();
  renderInjuries();
  renderUpcomingMatches();
  renderTrainingSchedule();
  renderReadiness();
  renderPlayerAlerts();
  renderNotifications();
  renderPlayerInsights();
  renderWellnessChart();
  renderAttendanceChart();
  renderReadinessChart();
  setupNotificationActions();
}

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

  showLoader("Loading player dashboard...");

  try {
    const hasPlayerProfile = await loadPlayerRecord();

    if (!hasPlayerProfile) return;

    await loadPlayerData();
    await createWellnessReminderNotification();
    await loadPlayerData();
    renderDashboard();
    
    setInterval(async () => {
      try {
        await loadPlayerData();
        await createWellnessReminderNotification();
        await loadPlayerData();
        renderDashboard();
      } catch (error) {
        console.error(
          "Auto refresh failed:",
          error
        );
      }
    }, 60000);
  } catch (error) {
    console.error("Player dashboard error:", error);

    setText(playerStatus, "Error");

    if (playerWellnessList) {
      playerWellnessList.innerHTML = `
        <div class="list-item">
          <strong>Error loading player dashboard.</strong>
          <p>${error.message}</p>
        </div>
      `;
    }

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