import React, {
  ReactNode,
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react';
import Logger from 'src/application/logging/logger';
import { useLocalStorage } from 'src/contexts/localStorageContext';
import { useSetAtom } from 'jotai';
import { userIdAtom } from 'src/atoms/app';
import { UserIdentityService } from 'src/services/userIdentityService';

const logger = new Logger('userIdentityContext');

export interface UserIdentityContextType {
  getUserIdOrDefault: () => Promise<string>;
  getUserIdOverrideFromLocalStorage: () => string | undefined;
  setUserIdOverrideInLocalStorage: (userId: string) => string;
  clearUserIdOverrideInLocalStorage: () => void;
  isReady: boolean;
}

const UserIdentityContext = createContext<UserIdentityContextType | undefined>(undefined);

interface UserIdentityProviderProps {
  userIdService: UserIdentityService;
  children: ReactNode;
}

export const UserIdentityProvider: React.FC<UserIdentityProviderProps> = ({
  userIdService: inputService,
  children,
}) => {
  const [localUserId, setLocalUserId] = useState<string | undefined>(undefined);
  const setUserId = useSetAtom(userIdAtom);
  const { getItem, setItem, isAvailable: localStorageIsReady } = useLocalStorage();

  const [isReady, setIsReady] = useState(false);

  useEffect(() => {
    // Assuming CommerceApiClient and other dependencies are ready if localStorage is.
    // In a more complex scenario, you might have more checks here.
    setIsReady(localStorageIsReady);
  }, [localStorageIsReady]);

  const USER_ID_OVERRIDE_KEY = 'v1-spiffy-user-id-override';

  // @deprecated
  const getUserIdOverrideFromLocalStorage = useCallback((): string | undefined => {
    return getItem(USER_ID_OVERRIDE_KEY) ?? undefined;
  }, [getItem]);

  const setUserIdOverrideInLocalStorage = useCallback(
    (userId: string): string => {
      logger.logInfo(`setUserIdOverrideInLocalStorage - Setting user_id=${userId}`);
      setItem(USER_ID_OVERRIDE_KEY, userId);
      // window.dispatchEvent is handled by useLocalStorage now
      return userId;
    },
    [setItem, USER_ID_OVERRIDE_KEY],
  );

  const clearUserIdOverrideInLocalStorage = useCallback(() => {
    logger.logInfo(`clearUserIdOverrideInLocalStorage - Clearing user_id`);
    // LocalStorageService.getLocalStorage()?.removeItem(USER_ID_OVERRIDE_KEY);
    // window.dispatchEvent is handled by useLocalStorage now
    setItem(USER_ID_OVERRIDE_KEY, ''); // Set to empty string to clear
  }, [setItem, USER_ID_OVERRIDE_KEY]);

  const getUserIdOrDefault = useCallback(async (): Promise<string> => {
    const userIdOverride = getUserIdOverrideFromLocalStorage();
    if (userIdOverride) {
      return userIdOverride;
    }

    try {
      // NOTE: This uses EnviveAnalytics under the hood to determine the userID
      const enviveUserId = await inputService.getUserIdOrDefault();

      if (!enviveUserId) {
        throw new Error(
          'EnviveAnalytics.resolveEnviveUserId() returned null/undefined - this should never happen',
        );
      }

      return enviveUserId;
    } catch (error: unknown) {
      logger.logError('CRITICAL: Failed to get user ID from EnviveAnalytics', error);
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      throw new Error(`CRITICAL: User ID resolution failed: ${errorMessage}`);
    }
  }, [getUserIdOverrideFromLocalStorage]);

  const value = useMemo(
    () => ({
      getUserIdOrDefault,
      getUserIdOverrideFromLocalStorage,
      setUserIdOverrideInLocalStorage,
      clearUserIdOverrideInLocalStorage,
      isReady,
    }),
    [
      getUserIdOrDefault,
      getUserIdOverrideFromLocalStorage,
      setUserIdOverrideInLocalStorage,
      clearUserIdOverrideInLocalStorage,
      isReady,
    ],
  );
  useEffect(() => {
    if (isReady && !localUserId) {
      const setUserIdStates = async () => {
        const newUserId = await getUserIdOrDefault();
        setLocalUserId(newUserId);
        setUserId(newUserId);
      };
      setUserIdStates();
    }
  }, [getUserIdOrDefault, isReady, localUserId, setUserId]);

  if (!localUserId) {
    return null;
  }
  return <UserIdentityContext.Provider value={value}>{children}</UserIdentityContext.Provider>;
};

export const useUserIdentity = () => {
  const context = useContext(UserIdentityContext);
  if (!context) {
    throw new Error('useUserIdentity must be used within a UserIdentityProvider');
  }
  return context;
};
