import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
} from 'react';

import { captureException, withScope } from '@sentry/browser';
import {
  fetchAndActivate,
  getBoolean,
  getNumber,
  getString,
} from 'firebase/remote-config';

import {
  defaultConfig,
  type FeatureFlagKey,
  type FeatureFlagValues,
  remoteConfig,
} from 'src/config/firebase';

type FlagResult<T> = {
  value: T;
  isLoading: boolean;
};

type FeatureFlagsContextValue = {
  isLoading: boolean;
};

const FeatureFlagsContext = createContext<FeatureFlagsContextValue | null>(
  null,
);

/**
 * Internal utility to get feature flag value from Firebase Remote Config or fallback to defaults
 */
function getFeatureFlagValue<K extends FeatureFlagKey>(
  flagName: K,
  options: { isRemoteConfig?: boolean } = { isRemoteConfig: true },
) {
  if (!remoteConfig || !options.isRemoteConfig) {
    const defaultValue = defaultConfig[flagName];
    return defaultValue;
  }

  const defaultValue = defaultConfig[flagName];
  const expectedType = typeof defaultValue;

  switch (expectedType) {
    case 'boolean':
      return getBoolean(remoteConfig, flagName);
    case 'string':
      return getString(remoteConfig, flagName);
    case 'number':
      return getNumber(remoteConfig, flagName);
    case 'object':
      try {
        const stringValue = getString(remoteConfig, flagName);
        return JSON.parse(stringValue);
      } catch (error) {
        // If parsing fails, return default value
        return defaultValue;
      }
    default:
      return defaultValue;
  }
}

function useFeatureFlagsContext(): FeatureFlagsContextValue {
  const context = useContext(FeatureFlagsContext);

  if (!context) {
    throw new Error(
      'Feature flag hooks must be used within a FeatureFlagsProvider',
    );
  }

  return context;
}

export const FeatureFlagsProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const initializeFlags = async () => {
      if (!remoteConfig) {
        setIsLoading(false);
        return;
      }

      try {
        await fetchAndActivate(remoteConfig);
      } catch (error) {
        withScope(scope => {
          scope.setTag('source', 'feature-flags-context');
          scope.setContext('feature-flags', {
            action: 'fetchAndActivate',
            location: 'FeatureFlagsProvider',
            description: 'Error fetching remote config values from Firebase',
          });
          captureException(error);
        });
      } finally {
        setIsLoading(false);
      }
    };

    initializeFlags();
  }, []);

  return (
    <FeatureFlagsContext.Provider value={{ isLoading }}>
      {children}
    </FeatureFlagsContext.Provider>
  );
};

/**
 * Hook to get a specific feature flag with proper typing
 * @param flagName - The feature flag key
 * @returns Object with the typed value and loading state
 * @deprecated use src/hooks/useFeatureFlag instead
 */
export function useFeatureFlag<K extends FeatureFlagKey>(
  flagName: K,
): FlagResult<FeatureFlagValues[K]> {
  const { isLoading } = useFeatureFlagsContext();

  const value = getFeatureFlagValue(flagName, {
    isRemoteConfig: !isLoading,
  });

  return { value, isLoading };
}

/**
 * Hook that returns a function to check feature flags dynamically
 * Useful for checking flags in any component directly on a fn and not using a hook
 * @returns Object containing checkFeatureFlag function
 * @deprecated use src/hooks/useFeatureFlag instead
 */
export function useFeatureFlagChecker() {
  const { isLoading } = useFeatureFlagsContext();

  const checkFeatureFlag = useCallback(
    (flagName: FeatureFlagKey) =>
      getFeatureFlagValue(flagName, {
        isRemoteConfig: !isLoading,
      }),
    [isLoading],
  );

  return { checkFeatureFlag };
}

export default FeatureFlagsContext;

/* 
========================================
FEATURE FLAGS CONFIGURATION GUIDE
========================================

To enable feature flags across different environments:

1. Firebase Console Setup:
   - Go to Firebase Console
   - Navigate to Remote Config section
   - Add a new parameter with the exact name from FEATURE_FLAG_KEYS

2. Environment Configuration:
   - Add the flag to the environment configuration in Firebase Console
   - Set appropriate values for development/production

3. Value Types:
   - boolean: true or false
   - string: 'any string value'
   - number: numeric values (123, 3.14, etc.)
   - object: JSON.stringify({key: 'value'})

4. Usage Examples:
   Single flag:
   ```tsx
   const { value, isLoading } = useFeatureFlag(
     FEATURE_FLAG_KEYS.TEST_EXAMPLE_BOOLEAN, 
   );
   const { value, isLoading } = useFeatureFlag<TestConfig>(
     FEATURE_FLAG_KEYS.TEST_EXAMPLE_OBJECT,
   );
   ```
   
   Function to check a specific feature flag using a function and not a hook
   ```tsx
   const { checkFeatureFlag } = useFeatureFlagChecker();
   
   // Filter items based on feature flags
   const filteredItems = items.filter(item => {
     if (item.type === 'employee_lifecycle') {
       return checkFeatureFlag(FEATURE_FLAG_KEYS.ENABLE_EMPLOYEE_LIFECYCLE);
     }
     return true;
   });
   
   ```
*/
