import { SessionUser } from '@imphnen-frontend-service/utils';
import { hackathonApi, SessionToken } from '@imphnen-frontend-service/service';
import { LoaderFunctionArgs, redirect } from 'react-router';

const mappingPublicRoutes = [
  '/',
];

const mappingOnboardingRoutes = [
  '/onboarding/user',
];

const mappingRoutePermissions = [
  {
    path: '/dashboard',
    permissions: [],
  },
  {
    path: '/teams/browse',
    permissions: [],
  },
  {
    path: '/teams/create',
    permissions: [],
  },
];

const mappingPublicPrefixRoutes = [
  '/hackathons',
];

// Cache to prevent redundant checks (cache for 5 seconds)
const onboardingCache = new Map<string, { hasLocation: boolean; timestamp: number }>();
const CACHE_DURATION = 5000; // 5 seconds

export const middleware = async ({ request }: LoaderFunctionArgs) => {
  const url = new URL(request.url);
  const pathname = url.pathname;

  // Get token from cookies and user from local storage
  const tokenData = SessionToken.get();
  const user = SessionUser.get();
  const isAuthenticated = !!tokenData?.token?.access_token;

  // Allow to access the hackathon pages without authentication
  if (mappingPublicPrefixRoutes.some((prefix) => pathname.startsWith(prefix))) {
    return null;
  }

  // Public routes - allow everyone to view the landing page
  if (mappingPublicRoutes.includes(pathname)) {
    return null;
  }

  // Auth callback - allow without authentication check (for OAuth callback)
  if (pathname === '/auth/callback') {
    return null;
  }

  // Auth routes (all /auth/* paths) - redirect to dashboard if already authenticated
  if (pathname.startsWith('/auth')) {
    if (isAuthenticated) return redirect('/dashboard');
    return null;
  }

  // Require authentication for all other routes
  if (!isAuthenticated) {
    return redirect('/auth/login');
  }

  // Check if user has completed onboarding
  // Skip onboarding check for onboarding routes themselves
  if (!mappingOnboardingRoutes.includes(pathname)) {
    try {
      const userId = user?.id;
      if (!userId) {
        return redirect('/auth/login');
      }

      const now = Date.now();

      // Check cache first
      const cached = onboardingCache.get(userId);
      let hasLocation = false;

      if (cached && (now - cached.timestamp) < CACHE_DURATION) {
        hasLocation = cached.hasLocation;
      } else {
        // First check user data (faster)
        if (user?.location) {
          hasLocation = true;
        } else {
          // Fetch from backend API
          try {
            const response = await hackathonApi.get('/users/me');
            hasLocation = !!response.data?.data?.location;
          } catch {
            // If API fails, check user data as fallback
            hasLocation = !!user?.location;
          }
        }

        // Update cache
        onboardingCache.set(userId, { hasLocation, timestamp: now });
      }

      if (!hasLocation) {
        return redirect('/onboarding/user');
      }
    } catch (error) {
      console.error('[Middleware] Unexpected error checking onboarding:', error);
      // On error, allow access (fail open)
      return null;
    }
  }

  // Check route permissions using user data
  const userPermissions =
    user?.role?.permissions?.map?.((perm) => perm?.name) ?? [];

  const matchedRoute = mappingRoutePermissions.find(
    (route) => route.path === pathname
  );

  if (matchedRoute) {
    const hasPermission =
      !matchedRoute.permissions ||
      matchedRoute.permissions.some((perm) => userPermissions.includes(perm));

    if (!hasPermission) {
      return redirect('/dashboard');
    }
  }

  return null;
};
