import { Navigate, useLocation, useNavigate } from 'react-router-dom';
import { ReactNode, useEffect } from 'react';
import { routes } from '../AppRoutes';
import { useMsal } from '@azure/msal-react';
import { match } from 'path-to-regexp';
import { useAuth } from './AuthProvider';
import { getInstructors, updateInstructor } from '../api/Users';
import { useToast } from '../components/Toast/ToastContext';

interface ProtectedRouteProps {
  children: ReactNode;
}

export const matchRoute = (pattern: string, resolvedPath: string) => {
  const matcher = match(pattern, { decode: decodeURIComponent });
  const result = matcher(resolvedPath);
  return result ? result.params : null;
};

export const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
  // Retrieve current auth information
  const { instance } = useMsal();
  const account = instance.getActiveAccount();
  const { user, loading } = useAuth();

  if (!account || (!user && !loading)) {
    return <Navigate to='/login' />;
  }

  const { addToast } = useToast();
  const navigate = useNavigate();
  const location = useLocation();
  useEffect(() => {
    const finishOwnershipTransfer = async () => {
      const instructors = await getInstructors();

      // Update incoming owner's is_admin property
      let response = await updateInstructor(user?.instructor_id as number, {
        is_admin: 'true',
      });
      // Extra check just in case, since this is a sensitive operation
      if (response.is_admin === 'true') {
        // Update outgoing owner's is_admin property
        const outgoing = instructors.find(
          (instructor) =>
            instructor.is_admin === 'true' &&
            instructor.instructor_id !== user?.instructor_id
        );
        response = await updateInstructor(outgoing?.instructor_id as number, {
          is_admin: 'false',
        });

        // Trigger a soft page refresh to ensure user can see admin-protected elements after change
        navigate(location.pathname, { replace: true });

        addToast('Ownership transfer process completed.', 'success');
      } else {
        addToast('Ownership transfer process failed.', 'danger');
      }
    };

    if (user?.is_admin === 'incoming') {
      finishOwnershipTransfer();
    }
  }, [user]);

  // Find the route that matches the current pathname
  // Handles cases like roster page where :sectionId (or etc.) is replaced with an actual value
  const route = routes.find((route) =>
    matchRoute(route.path, location.pathname)
  );
  if (user && !route?.allowedUserTypes.includes(user.type)) {
    // Redirect unauthorized users
    return <Navigate to='/unauthorized' replace />;
  }

  return children;
};
