import React, { useEffect } from "react";
import { useAuth } from "~/contexts/auth-context";
import { useLocation, useNavigate } from "react-router";
import toast from "react-hot-toast";

interface GlobalRouteGuardProps {
  children: React.ReactNode;
}

// Define protected routes that require authentication
const PROTECTED_ROUTES = [
  "/dashboard",
  "/dashboard/projects",
  "/dashboard/teams",
  "/dashboard/reports",
  "/dashboard/settings",
  "/profile",
  "/settings",
  "/admin",
];

// Define public routes that don't require authentication
const PUBLIC_ROUTES = [
  "/",
  "/login",
  "/forgot-password",
  "/reset-password",
  "/404",
  "/unauthorized",
];

// Define routes that authenticated users shouldn't access
const AUTH_RESTRICTED_ROUTES = [
  "/login",
  "/forgot-password",
  "/reset-password",
];

// Define exact routes (for root path handling)
const EXACT_ROUTES = ["/", "/login", "/dashboard", "/404", "/unauthorized"];

export function GlobalRouteGuard({ children }: GlobalRouteGuardProps) {
  const { isAuthenticated, isLoading, token, user, validateToken } = useAuth();
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    // Don't do anything while authentication is loading
    if (isLoading) return;

    const currentPath = location.pathname;

    // Check if current route is protected
    const isProtectedRoute = PROTECTED_ROUTES.some(
      (route) => currentPath === route || currentPath.startsWith(route + "/"),
    );

    // Check if current route is auth-restricted (like login page)
    const isAuthRestrictedRoute = AUTH_RESTRICTED_ROUTES.some(
      (route) => currentPath === route || currentPath.startsWith(route + "/"),
    );

    // Check if current route is a known public route
    const isPublicRoute = PUBLIC_ROUTES.some(
      (route) => currentPath === route || currentPath.startsWith(route + "/"),
    );

    // Check if it's an exact route match
    const isExactRoute = EXACT_ROUTES.includes(currentPath);

    // Case 1: User accessing protected route without authentication
    if (isProtectedRoute && !isAuthenticated) {
      toast.error("برای دسترسی به این صفحه باید وارد شوید");

      // Save the intended destination for after login
      const returnTo = encodeURIComponent(currentPath + location.search);
      navigate(`/login?returnTo=${returnTo}`, { replace: true });
      return;
    }

    // Case 2: User accessing protected route with expired/invalid token
    if (isProtectedRoute && isAuthenticated && (!token || !token.accessToken)) {
      toast.error("جلسه کاری شما منقضی شده است. لطفاً دوباره وارد شوید");

      // Clear invalid auth data
      localStorage.removeItem("auth_user");
      localStorage.removeItem("auth_token");

      navigate("/login", { replace: true });
      return;
    }

    // Case 3: Authenticated user trying to access auth-restricted routes
    if (isAuthRestrictedRoute && isAuthenticated && token?.accessToken) {
      // Get return URL from query params, default to dashboard
      const searchParams = new URLSearchParams(location.search);
      const returnTo = searchParams.get("returnTo");
      const redirectPath =
        returnTo && returnTo !== "/login" ? returnTo : "/dashboard";

      navigate(redirectPath, { replace: true });
      return;
    }

    // Case 4: Handle root path redirection
    if (currentPath === "/") {
      if (isAuthenticated && token?.accessToken) {
        navigate("/dashboard", { replace: true });
      } else {
        navigate("/login", { replace: true });
      }
      return;
    }

    // Case 5: Unknown/404 routes
    const isKnownRoute = isProtectedRoute || isPublicRoute || isExactRoute;

    if (
      !isKnownRoute &&
      !currentPath.includes("/404") &&
      !currentPath.includes("/unauthorized")
    ) {
      // If user is authenticated, show authenticated 404
      if (isAuthenticated && token?.accessToken) {
        navigate("/404", { replace: true });
      } else {
        // If user is not authenticated, redirect to login
        toast.error("صفحه مورد نظر یافت نشد. لطفاً وارد شوید");
        navigate("/login", { replace: true });
      }
      return;
    }

    // Case 6: Validate token for protected routes periodically
    if (isProtectedRoute && isAuthenticated && token?.accessToken) {
      const checkTokenValidity = async () => {
        try {
          const isValid = await validateToken();
          if (!isValid) {
            toast.error("جلسه کاری شما منقضی شده است");
            navigate("/unauthorized?reason=token-expired", { replace: true });
          }
        } catch (error) {
          console.error("Token validation failed:", error);
          navigate("/unauthorized?reason=token-expired", { replace: true });
        }
      };

      // Only check token validity every 30 seconds to avoid excessive API calls
      const now = Date.now();
      const lastCheck = parseInt(
        sessionStorage.getItem("lastTokenCheck") || "0",
      );

      if (now - lastCheck > 30000) {
        // 30 seconds
        sessionStorage.setItem("lastTokenCheck", now.toString());
        checkTokenValidity();
      }
    }
  }, [
    isLoading,
    isAuthenticated,
    token,
    user,
    location.pathname,
    location.search,
    navigate,
  ]);

  // Validate token periodically for authenticated users
  useEffect(() => {
    if (!isAuthenticated || !token?.accessToken) return;

    const validateTokenPeriodically = async () => {
      try {
        const isValid = await validateToken();
        if (!isValid) {
          toast.error("جلسه کاری شما منقضی شده است. لطفاً دوباره وارد شوید");
          navigate("/login", { replace: true });
        }
      } catch (error) {
        console.error("Token validation error:", error);
      }
    };

    // Validate token immediately
    validateTokenPeriodically();

    // Set up periodic validation (every 5 minutes)
    const interval = setInterval(validateTokenPeriodically, 5 * 60 * 1000);

    return () => clearInterval(interval);
  }, [isAuthenticated, token, validateToken, navigate]);

  // Show loading screen while checking authentication
  if (isLoading) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800">
        <div className="text-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-green-500 mx-auto mb-4"></div>
          <p className="text-gray-600 dark:text-gray-400 font-persian">
            در حال بررسی احراز هویت...
          </p>
        </div>
      </div>
    );
  }

  // Render children if all checks pass
  return <>{children}</>;
}

// Hook to check if user can access a specific route
export function useRouteAccess() {
  const { isAuthenticated, token } = useAuth();
  const location = useLocation();

  const canAccessRoute = (path: string): boolean => {
    const isProtectedRoute = PROTECTED_ROUTES.some(
      (route) => path === route || path.startsWith(route + "/"),
    );

    if (isProtectedRoute) {
      return isAuthenticated && !!token?.accessToken;
    }

    return true; // Public routes are accessible to everyone
  };

  const getCurrentRouteAccess = () => {
    return canAccessRoute(location.pathname);
  };

  return {
    canAccessRoute,
    getCurrentRouteAccess,
    isAuthenticated,
    hasValidToken: !!token?.accessToken,
  };
}
