"use client";

import { useEffect, useRef } from "react";
import { useSession } from "next-auth/react";

const TWO_HOURS_MS = 2 * 60 * 60 * 1000;

function getExpiryFromSession(session: {
  accessToken?: string;
  accessTokenExpires?: number;
} | null): number | null {
  if (!session) return null;
  if (typeof session.accessTokenExpires === "number") {
    return session.accessTokenExpires;
  }

  const accessToken = session.accessToken;
  if (!accessToken) return null;

  try {
    const segment = accessToken.split(".")[1];
    if (!segment) return null;
    const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
    const pad = (4 - (base64.length % 4)) % 4;
    const payload = JSON.parse(atob(base64 + "=".repeat(pad))) as {
      exp?: number;
    };
    return typeof payload.exp === "number" ? payload.exp * 1000 : null;
  } catch {
    return null;
  }
}

export function SessionExpiryGuard() {
  const { data: session, status } = useSession();
  const signOutStartedRef = useRef(false);

  useEffect(() => {
    if (status !== "authenticated") {
      signOutStartedRef.current = false;
      return;
    }

    const expiresAt =
      getExpiryFromSession(session ?? null) ?? Date.now() + TWO_HOURS_MS;

    const forceExpiryLogout = () => {
      if (signOutStartedRef.current) return;
      signOutStartedRef.current = true;
      void import("@/lib/client-sign-out").then(({ clientSignOut }) => {
        void clientSignOut({
          callbackUrl: "/session-revoked?reason=expired",
          redirect: true,
        });
      });
    };

    const checkExpiry = () => {
      if (Date.now() >= expiresAt) {
        forceExpiryLogout();
      }
    };

    checkExpiry();

    const timeoutMs = Math.max(0, expiresAt - Date.now());
    const expiryTimeout = window.setTimeout(checkExpiry, timeoutMs);
    const safetyInterval = window.setInterval(checkExpiry, TWO_HOURS_MS);

    window.addEventListener("focus", checkExpiry);
    document.addEventListener("visibilitychange", checkExpiry);

    return () => {
      window.clearTimeout(expiryTimeout);
      window.clearInterval(safetyInterval);
      window.removeEventListener("focus", checkExpiry);
      document.removeEventListener("visibilitychange", checkExpiry);
    };
  }, [session, status]);

  return null;
}
