// =========================================================
// FILE: app-guard.js | TYPE: Route Protection + Role Access
// =========================================================

import { auth, db } from "./firebase-config.js";

import {
  onAuthStateChanged,
  signOut
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-auth.js";

import {
  collection,
  doc,
  getDoc,
  onSnapshot,
  query,
  where
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

export let currentUser = null;
export let currentUserProfile = null;

let unsubscribeNotificationBadge = null;
let logoutButtonIsReady = false;

const PUBLIC_PAGES = [
  "index.html",
  "login.html",
  "register.html",
  "reset-password.html",
  "legal-acceptance.html"
];

const REPORT_PAGES = [
  "reports.html",
  "report-readiness.html",
  "report-training-load.html",
  "report-team-overview.html",
  "report-player-performance.html",
  "report-attendance.html",
  "report-wellness.html",
  "report-injury-risk.html",
  "report-match-readiness.html"
];

const ROLE_PERMISSIONS = {
  director: [
    "dashboard.html",
    "profile.html",
    "subscription.html",
    "teams.html",
    "matches.html",
    "training.html",
    "training-attendance.html",
    "players.html",
    "attendance.html",
    "wellness.html",
    "injuries.html",
    "player-detail.html",
    "match-readiness.html",
    "match-centre.html",
    "team-sheet.html",
    "team-performance.html",
    "post-match-report.html",
    "notifications.html",
    "user-management.html",
    "organisation-settings.html",
    ...REPORT_PAGES
  ],

  coach: [
    "dashboard.html",
    "profile.html",
    "matches.html",
    "training.html",
    "training-attendance.html",
    "players.html",
    "attendance.html",
    "wellness.html",
    "injuries.html",
    "player-detail.html",
    "match-readiness.html",
    "match-centre.html",
    "team-sheet.html",
    "team-performance.html",
    "notifications.html",
    "post-match-report.html",
    ...REPORT_PAGES
  ],

  player: [
    "player-dashboard.html",
    "profile.html",
    "player-detail.html",
    "player-match-detail.html",
    "wellness.html",
    "attendance.html",
    "match-readiness.html",
    "notifications.html"
  ],

  biokineticist: [
    "bio-dashboard.html",
    "profile.html",
    "players.html",
    "wellness.html",
    "bio-wellness.html",
    "injuries.html",
    "player-detail.html",
    "notifications.html",
    ...REPORT_PAGES
  ]
};

const ROLE_HOME_PAGES = {
  director: "dashboard.html",
  coach: "dashboard.html",
  player: "player-dashboard.html",
  biokineticist: "bio-dashboard.html"
};

function getCurrentPage() {
  const path = window.location.pathname;
  const page = path.substring(path.lastIndexOf("/") + 1);
  return page || "index.html";
}

function getRoleHomePage(role) {
  return ROLE_HOME_PAGES[role] || "login.html";
}

function isPublicPage(page) {
  return PUBLIC_PAGES.includes(page);
}

function userCanAccessPage(role, page) {
  const allowedPages = ROLE_PERMISSIONS[role] || [];
  return allowedPages.includes(page);
}

function redirectToRoleHome(role) {
  window.location.href = getRoleHomePage(role);
}

function redirectToLogin() {
  window.location.href = "login.html";
}

function formatRole(role) {
  if (!role) return "User";
  if (role === "biokineticist") return "Biokineticist";
  return role.charAt(0).toUpperCase() + role.slice(1);
}

function subscriptionAllowsAccess(subscription = {}) {
  if (subscription.isDemo || subscription.status === "demo") {
    return true;
  }

  if (subscription.active === true && subscription.status === "active") {
    return true;
  }

  if (subscription.status === "trial") {
    const trialEndsAt = subscription.trialEndsAt?.toDate
      ? subscription.trialEndsAt.toDate()
      : subscription.trialEndsAt
        ? new Date(subscription.trialEndsAt)
        : null;

    if (!trialEndsAt) return false;

    return trialEndsAt.getTime() >= Date.now();
  }

  return false;
}

function showGuardMessage(message) {
  console.warn("[TryTrack Guard]", message);

  if (typeof window.showToast === "function") {
    window.showToast(message, "error");
  } else {
    // Use toast notification system instead of alert()
    if (window.showToast) { window.showToast(message, "error"); }
  }
}

function clearNotificationBadgeListener() {
  if (unsubscribeNotificationBadge) {
    unsubscribeNotificationBadge();
    unsubscribeNotificationBadge = null;
  }
}

export function applyRoleSidebar(profile) {
  if (!profile?.role) return;

  const role = profile.role;

  document.querySelectorAll("[data-role-access]").forEach((element) => {
    const allowedRoles = element.dataset.roleAccess
      .split(",")
      .map((item) => item.trim())
      .filter(Boolean);

    element.classList.toggle("hidden", !allowedRoles.includes(role));
  });
}

function applyActiveSidebarLink() {
  const currentPage = getCurrentPage();

  document.querySelectorAll(".sidebar-nav a").forEach((link) => {
    const href = link.getAttribute("href");
    if (!href) return;

    const linkPage = href.substring(href.lastIndexOf("/") + 1);
    link.classList.toggle("active", linkPage === currentPage);
  });
}

function updateSidebarUser(profile, user) {
  const userDisplay = document.getElementById("userDisplay");
  const avatar = document.querySelector(".sidebar-user-avatar");

  if (!userDisplay) {
    console.warn("[TryTrack Guard] userDisplay not found in sidebar.");
    return;
  }

  const displayName = profile.fullName || user.email || "User";
  const displayRole = formatRole(profile.role);

  userDisplay.innerHTML = `
    <span class="sidebar-user-name">${displayName}</span>
    <span class="sidebar-user-role">${displayRole}</span>
  `;

  if (avatar) {
    const initials = displayName
      .split(" ")
      .map((part) => part.charAt(0))
      .join("")
      .slice(0, 2)
      .toUpperCase();

    avatar.textContent = initials || "TT";
  }
}

function userCanAccessNotification(notification, profile) {
  const role = profile.role;
  const assignedTeamIds = profile.assignedTeamIds || [];
  const assignedPlayerIds = profile.assignedPlayerIds || [];

  if (role === "director") {
    if (notification.userId) {
      return notification.userId === profile.uid;
    }

    return true;
  }

  if (role === "coach") {
    return (
      notification.userId === profile.uid ||
      Boolean(notification.teamId && assignedTeamIds.includes(notification.teamId))
    );
  }

  if (role === "biokineticist") {
    return (
      notification.userId === profile.uid ||
      Boolean(notification.teamId && assignedTeamIds.includes(notification.teamId)) ||
      Boolean(notification.playerId && assignedPlayerIds.includes(notification.playerId))
    );
  }

  if (role === "player") {
    const isOwnUserNotification =
      notification.userId === profile.uid;

    const isOwnPlayerNotification =
      notification.playerId === profile.playerId;

    const isTeamWideNotification =
      notification.teamId &&
      assignedTeamIds.includes(notification.teamId) &&
      (!notification.playerId || notification.playerId === "") &&
      (!notification.userId || notification.userId === "");

    return (
      isOwnUserNotification ||
      isOwnPlayerNotification ||
      isTeamWideNotification
    );
  }

  return false;
}

function setupNotificationBadge(profile) {
  const badge = document.getElementById("notificationBadge");

  if (!badge || !profile?.organisationId) return;

  clearNotificationBadgeListener();

  const badgeQueries = [];

  badgeQueries.push(
    query(
      collection(db, "notifications"),
      where("organisationId", "==", profile.organisationId),
      where("userId", "==", profile.uid)
    )
  );

  if (profile.playerId) {
    badgeQueries.push(
      query(
        collection(db, "notifications"),
        where("organisationId", "==", profile.organisationId),
        where("playerId", "==", profile.playerId)
      )
    );
  }

  const assignedTeamIds = profile.assignedTeamIds || [];

  assignedTeamIds.slice(0, 10).forEach((teamId) => {
    badgeQueries.push(
      query(
        collection(db, "notifications"),
        where("organisationId", "==", profile.organisationId),
        where("teamId", "==", teamId)
      )
    );
  });

  if (profile.role !== "player") {
    badgeQueries.length = 0;

    badgeQueries.push(
      query(
        collection(db, "notifications"),
        where("organisationId", "==", profile.organisationId)
      )
    );
  }

  const snapshotCache = [];

  function updateBadgeFromSnapshots() {
    const notificationMap = new Map();

    snapshotCache.filter(Boolean).forEach((snapshot) => {
      snapshot.docs.forEach((docSnap) => {
        notificationMap.set(docSnap.id, {
          id: docSnap.id,
          ...docSnap.data()
        });
      });
    });

    const unreadCount = Array.from(notificationMap.values())
      .filter((notification) => {
        const readBy = notification.readBy || {};

        return (
          userCanAccessNotification(notification, profile) &&
          !readBy[profile.uid]
        );
      })
      .length;

    if (unreadCount > 0) {
      badge.textContent = unreadCount > 99 ? "99+" : String(unreadCount);
      badge.classList.remove("hidden");
    } else {
      badge.textContent = "0";
      badge.classList.add("hidden");
    }
  }

  const unsubscribers = badgeQueries.map((badgeQuery, index) =>
    onSnapshot(
      badgeQuery,
      (snapshot) => {
        snapshotCache[index] = snapshot;
        updateBadgeFromSnapshots();
      },
      (error) => {
        console.error("Notification badge error:", error);
        badge.textContent = "0";
        badge.classList.add("hidden");
      }
    )
  );

  unsubscribeNotificationBadge = function () {
    unsubscribers.forEach((unsubscribe) => unsubscribe());
  };
}

async function loadUserProfile(user) {
  const userRef = doc(db, "users", user.uid);
  const userSnap = await getDoc(userRef);

  if (!userSnap.exists()) {
    return null;
  }

  return {
    uid: user.uid,
    email: user.email,
    ...userSnap.data()
  };
}

async function handleInvalidSession(message) {
  showGuardMessage(message);
  clearNotificationBadgeListener();
  await signOut(auth);
  redirectToLogin();
}

export function requireAuth(callback) {
  onAuthStateChanged(auth, async function (user) {
    const currentPage = getCurrentPage();

    if (!user) {
      clearNotificationBadgeListener();

      if (!isPublicPage(currentPage)) {
        redirectToLogin();
      }

      return;
    }

    currentUser = user;

    try {
      const profile = await loadUserProfile(user);

      if (!profile) {
        await handleInvalidSession("User profile not found. Please contact support.");
        return;
      }

      currentUserProfile = profile;

      const role = profile.role;

      if (!role) {
        await handleInvalidSession("No user role found. Please contact support.");
        return;
      }

      if (profile.status && profile.status !== "active") {
        await handleInvalidSession("Your account is not active. Please contact your organisation administrator.");
        return;
      }

      if (currentPage === "legal-acceptance.html") {
        return;
      }

      if (isPublicPage(currentPage)) {
        redirectToRoleHome(role);
        return;
      }

      const legal = profile.legalAcceptance || {};

      if (!legal.requiredAccepted) {
        window.location.href = "legal-acceptance.html";
        return;
      }

      if (!userCanAccessPage(role, currentPage)) {
        redirectToRoleHome(role);
        return;
      }
      
      if (!profile.organisationId) {
        await handleInvalidSession("No organisation linked to this user. Please contact support.");
        return;
      }
      
      const organisationRef = doc(db, "organisations", profile.organisationId);
      const organisationSnap = await getDoc(organisationRef);
    
      if (organisationSnap.exists()) {
        const organisation = organisationSnap.data();
        const subscription = organisation.subscription || {};
    
        const billingPages = [
          "subscription.html",
          "profile.html",
          "legal-acceptance.html",
          "notifications.html"
        ];
    
        if (!subscriptionAllowsAccess(subscription) && !billingPages.includes(currentPage)) {
          window.location.href = "subscription.html";
          return;
        }
      }

      updateSidebarUser(profile, user);
      applyRoleSidebar(profile);
      applyActiveSidebarLink();
      setupNotificationBadge(profile);

      if (typeof callback === "function") {
        await callback(currentUser, currentUserProfile);
      }
    } catch (error) {
      console.error("[TryTrack Guard] Auth guard error:", error);
      showGuardMessage("Could not load user profile: " + error.message);
    }
  });
}

export function setupLogoutButton() {
  const logoutBtn = document.getElementById("logoutBtn");

  if (!logoutBtn || logoutButtonIsReady) return;

  logoutButtonIsReady = true;

  logoutBtn.addEventListener("click", async function () {
    try {
      clearNotificationBadgeListener();
      await signOut(auth);
      redirectToLogin();
    } catch (error) {
      console.error("Logout error:", error);
      showGuardMessage("Logout failed: " + error.message);
    }
  });
}