"use client";
import { logger } from "@/lib/logger";

import { useEffect, useRef, useState } from "react";
import { useAuthSession } from "@/features/auth/services/auth.store";
import { Button } from "@/components/atoms/button";
import { useAuth } from "@/features/auth/hooks/use-auth";

interface SessionTimeoutWarningProps {
  warningTime?: number; // Minutes before token expires to show warning
}

export function SessionTimeoutWarning({
  warningTime = 5, // Show warning 5 minutes before expiry (reduced since we have auto-refresh)
}: SessionTimeoutWarningProps) {
  const { isAuthenticated, session } = useAuthSession();
  const { logout, refreshSession } = useAuth();
  const [showWarning, setShowWarning] = useState(false);
  const [timeLeft, setTimeLeft] = useState<number>(0);
  const expiryRef = useRef<number | null>(null);
  const dialogRef = useRef<HTMLDivElement | null>(null);
  const previouslyFocusedElement = useRef<HTMLElement | null>(null);

  useEffect(() => {
    if (!isAuthenticated || !session.accessExpiresAt) {
      expiryRef.current = null;
      setShowWarning(false);
      setTimeLeft(0);
      return undefined;
    }

    const expiryTime = Date.parse(session.accessExpiresAt);
    if (Number.isNaN(expiryTime)) {
      logger.warn("Invalid access token expiry", { expiresAt: session.accessExpiresAt });
      expiryRef.current = null;
      setShowWarning(false);
      setTimeLeft(0);
      return undefined;
    }

    expiryRef.current = expiryTime;

    if (Date.now() >= expiryTime) {
      void logout({ reason: "session-expired" });
      return undefined;
    }

    const warningThreshold = warningTime * 60 * 1000;
    const now = Date.now();
    const timeUntilExpiry = expiryTime - now;
    const timeUntilWarning = timeUntilExpiry - warningThreshold;

    if (timeUntilWarning <= 0) {
      setShowWarning(true);
      setTimeLeft(Math.max(1, Math.ceil(timeUntilExpiry / (60 * 1000))));
      return undefined;
    }

    const warningTimeout = setTimeout(() => {
      setShowWarning(true);
      setTimeLeft(Math.max(1, Math.ceil((expiryRef.current! - Date.now()) / (60 * 1000))));
    }, timeUntilWarning);

    return () => clearTimeout(warningTimeout);
  }, [isAuthenticated, session.accessExpiresAt, warningTime, logout]);

  useEffect(() => {
    if (!showWarning || !expiryRef.current) return undefined;

    previouslyFocusedElement.current = document.activeElement as HTMLElement | null;

    const focusTimer = window.setTimeout(() => {
      dialogRef.current?.focus();
    }, 0);

    const interval = setInterval(() => {
      const expiryTime = expiryRef.current;
      if (!expiryTime) {
        return;
      }

      const remaining = expiryTime - Date.now();
      if (remaining <= 0) {
        setTimeLeft(0);
        void logout({ reason: "session-expired" });
        return;
      }

      setTimeLeft(Math.max(1, Math.ceil(remaining / (60 * 1000))));
    }, 60000);

    return () => {
      clearInterval(interval);
      clearTimeout(focusTimer);
      previouslyFocusedElement.current?.focus();
    };
  }, [showWarning, logout]);

  useEffect(() => {
    if (!showWarning) return undefined;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "Escape") {
        event.preventDefault();
        setShowWarning(false);
        void logout({ reason: "session-expired" });
      }

      if (event.key === "Tab") {
        const focusableElements = dialogRef.current?.querySelectorAll<HTMLElement>(
          'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
        );

        if (!focusableElements || focusableElements.length === 0) {
          event.preventDefault();
          return;
        }

        const firstElement = focusableElements[0];
        const lastElement = focusableElements[focusableElements.length - 1];

        if (!event.shiftKey && document.activeElement === lastElement) {
          event.preventDefault();
          firstElement.focus();
        }

        if (event.shiftKey && document.activeElement === firstElement) {
          event.preventDefault();
          lastElement.focus();
        }
      }
    };

    document.addEventListener("keydown", handleKeyDown);

    return () => {
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, [showWarning, logout]);

  const handleExtendSession = () => {
    void (async () => {
      try {
        await refreshSession();
        setShowWarning(false);
        setTimeLeft(0);
      } catch (error) {
        logger.error("Failed to extend session", error);
        await logout({ reason: "session-expired" });
      }
    })();
  };

  const handleLogoutNow = () => {
    void logout({ reason: "session-expired" });
    setShowWarning(false);
  };

  if (!showWarning) {
    return null;
  }

  return (
    <div
      className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
      role="presentation"
      aria-hidden={!showWarning}
    >
      <div
        ref={dialogRef}
        role="dialog"
        aria-modal="true"
        aria-labelledby="session-timeout-title"
        aria-describedby="session-timeout-description"
        tabIndex={-1}
        className="bg-white rounded-lg p-6 max-w-md w-full mx-4 shadow-xl outline-none"
      >
        <div className="flex items-center gap-2 mb-4">
          <span className="text-yellow-500 text-xl">⚠️</span>
          <h2 id="session-timeout-title" className="text-lg font-semibold">
            Session Expiring Soon
          </h2>
        </div>

        <p id="session-timeout-description" className="text-gray-600 mb-6">
          Your session will expire in{" "}
          <strong>
            {timeLeft} minute{timeLeft !== 1 ? "s" : ""}
          </strong>
          . Would you like to extend your session?
        </p>

        <div className="flex gap-2 justify-end">
          <Button variant="outline" onClick={handleLogoutNow}>
            Logout Now
          </Button>
          <Button onClick={handleExtendSession}>Extend Session</Button>
        </div>
      </div>
    </div>
  );
}
