/**
 * Authentication Hooks
 */

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  login,
  logout,
  getCurrentUser,
  masquerade,
  stopMasquerade,
  forgotPassword,
  LoginCredentials,
  User,
  MasqueradeStackEntry
} from '../api/auth';
import { getCookie, setCookie, deleteCookie } from '../utils/cookies';
import { getBaseDomain, buildSubdomainUrl } from '../utils/domain';

/**
 * Helper hook to set auth tokens (used by invitation acceptance)
 */
export const useAuth = () => {
  const queryClient = useQueryClient();

  const setTokens = (accessToken: string, refreshToken: string) => {
    setCookie('access_token', accessToken, 7);
    setCookie('refresh_token', refreshToken, 7);
  };

  return { setTokens };
};

/**
 * Hook to get current user
 */
export const useCurrentUser = () => {
  return useQuery<User | null, Error>({
    queryKey: ['currentUser'],
    queryFn: async () => {
      // Check if token exists before making request (from cookie)
      const token = getCookie('access_token');

      if (!token) {
        return null; // No token, return null instead of making request
      }
      try {
        return await getCurrentUser();
      } catch (error) {
        // If getCurrentUser fails (e.g., 401), return null
        // The API client interceptor will handle token refresh
        console.error('Failed to get current user:', error);
        return null;
      }
    },
    retry: 1, // Retry once in case of token refresh
    staleTime: 5 * 60 * 1000, // 5 minutes
    refetchOnMount: true, // Always refetch when component mounts
    refetchOnWindowFocus: false,
  });
};

/**
 * Hook to login
 */
export const useLogin = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: login,
    onSuccess: (data) => {
      // Store tokens in cookies for cross-subdomain access
      setCookie('access_token', data.access, 7);
      setCookie('refresh_token', data.refresh, 7);

      // Clear any existing masquerade stack - this is a fresh login
      localStorage.removeItem('masquerade_stack');

      // Set user in cache
      queryClient.setQueryData(['currentUser'], data.user);
    },
  });
};

/**
 * Hook to logout
 */
export const useLogout = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: logout,
    onSuccess: () => {
      // Clear tokens (from cookies)
      deleteCookie('access_token');
      deleteCookie('refresh_token');

      // Clear masquerade stack
      localStorage.removeItem('masquerade_stack');

      // Clear user cache
      queryClient.removeQueries({ queryKey: ['currentUser'] });
      queryClient.clear();

      // Redirect to login page on root domain
      const protocol = window.location.protocol;
      const baseDomain = getBaseDomain();
      const port = window.location.port ? `:${window.location.port}` : '';
      window.location.href = `${protocol}//${baseDomain}${port}/login`;
    },
  });
};

/**
 * Check if user is authenticated
 */
export const useIsAuthenticated = (): boolean => {
  const { data: user, isLoading } = useCurrentUser();
  return !isLoading && !!user;
};

/**
 * Get the redirect path based on user role
 * Tenant users go to /dashboard/, platform users go to /
 * Note: Backend maps tenant_owner -> owner, tenant_manager -> manager, etc.
 */
const getRedirectPathForRole = (role: string): string => {
  // Tenant roles (as returned by backend after role mapping)
  const tenantRoles = ['owner', 'manager', 'staff', 'customer'];
  if (tenantRoles.includes(role)) {
    return '/dashboard/';
  }
  return '/';
};

/**
 * Hook to masquerade as another user
 */
export const useMasquerade = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (user_pk: number) => {
      // Get current masquerading stack from localStorage
      const stackJson = localStorage.getItem('masquerade_stack');
      const currentStack: MasqueradeStackEntry[] = stackJson ? JSON.parse(stackJson) : [];

      // Call masquerade API with current stack
      return masquerade(user_pk, currentStack);
    },
    onSuccess: async (data) => {
      // Store the updated masquerading stack
      if (data.masquerade_stack) {
        localStorage.setItem('masquerade_stack', JSON.stringify(data.masquerade_stack));
      }

      const user = data.user;
      const currentHostname = window.location.hostname;
      const currentPort = window.location.port;
      const baseDomain = getBaseDomain();

      let targetSubdomain: string | null = null;

      if (['superuser', 'platform_manager', 'platform_support'].includes(user.role)) {
        targetSubdomain = 'platform';
      } else if (user.business_subdomain) {
        targetSubdomain = user.business_subdomain;
      }

      const needsRedirect = targetSubdomain && currentHostname !== `${targetSubdomain}.${baseDomain}`;
      const redirectPath = getRedirectPathForRole(user.role);

      if (needsRedirect) {
        // CRITICAL: Clear the session cookie BEFORE redirect
        // Call logout API to clear HttpOnly sessionid cookie
        try {
          const apiUrl = import.meta.env.VITE_API_URL || `${window.location.protocol}//${baseDomain}`;
          await fetch(`${apiUrl}/auth/logout/`, {
            method: 'POST',
            credentials: 'include',
          });
        } catch (e) {
          // Continue anyway
        }

        // Pass tokens AND masquerading stack in URL (for cross-domain transfer)
        const stackEncoded = encodeURIComponent(JSON.stringify(data.masquerade_stack || []));
        const redirectUrl = buildSubdomainUrl(targetSubdomain, `${redirectPath}?access_token=${data.access}&refresh_token=${data.refresh}&masquerade_stack=${stackEncoded}`);

        window.location.href = redirectUrl;
        return;
      }

      // If no redirect needed (same subdomain), we can just set cookies and navigate
      setCookie('access_token', data.access, 7);
      setCookie('refresh_token', data.refresh, 7);
      queryClient.setQueryData(['currentUser'], data.user);
      window.location.href = redirectPath;
    },
  });
};

/**
 * Hook to stop masquerading and return to previous user
 */
export const useStopMasquerade = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async () => {
      // Get current masquerading stack from localStorage
      const stackJson = localStorage.getItem('masquerade_stack');
      const currentStack: MasqueradeStackEntry[] = stackJson ? JSON.parse(stackJson) : [];

      if (currentStack.length === 0) {
        throw new Error('No masquerading session to stop');
      }

      // Call stop_masquerade API with current stack
      return stopMasquerade(currentStack);
    },
    onSuccess: async (data) => {
      // Update the masquerading stack
      if (data.masquerade_stack && data.masquerade_stack.length > 0) {
        localStorage.setItem('masquerade_stack', JSON.stringify(data.masquerade_stack));
      } else {
        // Clear the stack if empty
        localStorage.removeItem('masquerade_stack');
      }

      const user = data.user;
      const currentHostname = window.location.hostname;
      const currentPort = window.location.port;
      const baseDomain = getBaseDomain();

      let targetSubdomain: string | null = null;

      if (['superuser', 'platform_manager', 'platform_support'].includes(user.role)) {
        targetSubdomain = 'platform';
      } else if (user.business_subdomain) {
        targetSubdomain = user.business_subdomain;
      }

      const needsRedirect = targetSubdomain && currentHostname !== `${targetSubdomain}.${baseDomain}`;
      const redirectPath = getRedirectPathForRole(user.role);

      if (needsRedirect) {
        // CRITICAL: Clear the session cookie BEFORE redirect
        try {
          const apiUrl = import.meta.env.VITE_API_URL || `${window.location.protocol}//${baseDomain}`;
          await fetch(`${apiUrl}/auth/logout/`, {
            method: 'POST',
            credentials: 'include',
          });
        } catch (e) {
          // Continue anyway
        }

        // Pass tokens AND masquerading stack in URL (for cross-domain transfer)
        const stackEncoded = encodeURIComponent(JSON.stringify(data.masquerade_stack || []));
        const redirectUrl = buildSubdomainUrl(targetSubdomain, `${redirectPath}?access_token=${data.access}&refresh_token=${data.refresh}&masquerade_stack=${stackEncoded}`);

        window.location.href = redirectUrl;
        return;
      }

      // If no redirect needed (same subdomain), we can just set cookies and navigate
      setCookie('access_token', data.access, 7);
      setCookie('refresh_token', data.refresh, 7);
      queryClient.setQueryData(['currentUser'], data.user);
      window.location.href = redirectPath;
    },
  });
};

/**
 * Hook to request password reset
 */
export const useForgotPassword = () => {
  return useMutation({
    mutationFn: (data: { email: string }) => forgotPassword(data.email),
  });
};
