import React, { createContext, useContext, useState, useEffect, ReactNode, useRef } from 'react';
import type {
  SetupWizardStepConfig,
  StepValidationResult,
  CareerSetupState
} from '../types';

interface CareerWizardContextState {
  currentStepIndex: number;
  steps: SetupWizardStepConfig[];
  stepValidation: Map<string, StepValidationResult>;
  loading: boolean;
  error?: string;
  careerWizardState: CareerSetupState | null;
  refreshTrigger: number;
  scrollContainerRef: React.RefObject<HTMLDivElement>;
}

interface CareerWizardContextActions {
  goToStep: (index: number) => void;
  nextStep: () => void;
  previousStep: () => void;
  validateCurrentStep: () => Promise<StepValidationResult>;
  completeWizard: () => Promise<void>;
  dismissWizard: () => Promise<void>;
  refreshStepStatus: (stepId: string) => Promise<void>;
  refreshAllSteps: () => Promise<void>;
  triggerRefresh: () => void;
  scrollToTop: () => void;
}

type CareerWizardContextType = CareerWizardContextState & CareerWizardContextActions;

const CareerWizardContext = createContext<CareerWizardContextType | undefined>(undefined);

export const useCareerWizard = () => {
  const context = useContext(CareerWizardContext);
  if (!context) {
    throw new Error('useCareerWizard must be used within CareerWizardProvider');
  }
  return context;
};

interface CareerWizardProviderProps {
  children: ReactNode;
}

export const CareerWizardProvider: React.FC<CareerWizardProviderProps> = ({ children }) => {
  const [currentStepIndex, setCurrentStepIndex] = useState(0);
  const [steps, setSteps] = useState<SetupWizardStepConfig[]>([]);
  const [stepValidation, setStepValidation] = useState<Map<string, StepValidationResult>>(
    new Map()
  );
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string>();
  const [careerWizardState, setCareerWizardState] = useState<CareerSetupState | null>(null);
  const [refreshTrigger, setRefreshTrigger] = useState(0);
  const scrollContainerRef = useRef<HTMLDivElement>(null);

  // Load steps and initial state
  useEffect(() => {
    const loadInitialData = async () => {
      try {
        console.log('[CareerWizardContext] Preload loaded?:', (window as any).__CAREER_PRELOAD_LOADED__);
        console.log('[CareerWizardContext] window.careerWizardAPI:', window.careerWizardAPI);
        console.log('[CareerWizardContext] typeof window.careerWizardAPI:', typeof window.careerWizardAPI);

        if (!window.careerWizardAPI) {
          throw new Error('careerWizardAPI is not available on window. Preload script may not have loaded correctly.');
        }

        const [loadedSteps, state] = await Promise.all([
          window.careerWizardAPI.getSteps(),
          window.careerWizardAPI.getState()
        ]);

        setSteps(loadedSteps);
        setCareerWizardState(state);

        // Validate all steps in parallel (non-blocking)
        (async () => {
          const validations = new Map<string, StepValidationResult>();
          const startTime = performance.now();

          // Set all steps to loading initially
          const loadingValidations = new Map<string, StepValidationResult>();
          for (const step of loadedSteps) {
            loadingValidations.set(step.id, {
              isComplete: false,
              canProceed: false,
              isLoading: true
            });
          }
          setStepValidation(loadingValidations);

          console.log(`[Performance] Starting parallel validation of ${loadedSteps.length} steps...`);

          // Validate all steps in parallel using Promise.allSettled
          const validationPromises = loadedSteps.map(async (step) => {
            try {
              const result = await window.careerWizardAPI.validateStep(step.id);
              return { stepId: step.id, result: { ...result, isLoading: false }, error: null };
            } catch (err) {
              console.error(`Failed to validate step ${step.id}:`, err);
              return {
                stepId: step.id,
                result: {
                  isComplete: false,
                  canProceed: false,
                  isLoading: false
                },
                error: err
              };
            }
          });

          // Wait for all validations to complete
          const results = await Promise.allSettled(validationPromises);

          // Process results and update state
          const finalValidations = new Map<string, StepValidationResult>();
          results.forEach((promiseResult) => {
            if (promiseResult.status === 'fulfilled') {
              const { stepId, result } = promiseResult.value;
              finalValidations.set(stepId, result);
            }
          });

          // Update all validations at once for better performance
          setStepValidation(finalValidations);

          const endTime = performance.now();
          const duration = Math.round(endTime - startTime);
          console.log(`[Performance] ✓ Parallel validation completed in ${duration}ms`);
          console.log(`[Performance] Average per step: ${Math.round(duration / loadedSteps.length)}ms`);

          // Find first incomplete step
          const firstIncompleteIndex = loadedSteps.findIndex(step => {
            const validation = finalValidations.get(step.id);
            return !validation?.isComplete;
          });

          if (firstIncompleteIndex !== -1) {
            setCurrentStepIndex(firstIncompleteIndex);
          }
        })();
      } catch (err: any) {
        console.error('Failed to load careerWizard data:', err);
        setError(err.message);
      }
    };

    loadInitialData();
  }, []);

  const goToStep = (index: number) => {
    if (index >= 0 && index < steps.length) {
      setCurrentStepIndex(index);
    }
  };

  const nextStep = () => {
    if (currentStepIndex < steps.length - 1) {
      setCurrentStepIndex(currentStepIndex + 1);
    }
  };

  const previousStep = () => {
    if (currentStepIndex > 0) {
      setCurrentStepIndex(currentStepIndex - 1);
    }
  };

  const validateCurrentStep = async (): Promise<StepValidationResult> => {
    const currentStep = steps[currentStepIndex];
    if (!currentStep) {
      throw new Error('No current step');
    }

    try {
      // Set loading state
      setStepValidation(prev => {
        const current = prev.get(currentStep.id);
        return new Map(prev).set(currentStep.id, {
          ...current,
          isComplete: current?.isComplete ?? false,
          canProceed: current?.canProceed ?? false,
          isLoading: true
        });
      });

      const result = await window.careerWizardAPI.validateStep(currentStep.id);
      setStepValidation(prev => new Map(prev).set(currentStep.id, { ...result, isLoading: false }));

      // Reload fresh state from backend to avoid using stale React state
      const freshState = await window.careerWizardAPI.getState();
      const existingStepData = freshState.stepStatus[currentStep.id];
      const existingData = existingStepData?.data || {};

      const updatedState: CareerSetupState = {
        ...freshState,
        stepStatus: {
          ...freshState.stepStatus,
          [currentStep.id]: {
            completed: result.isComplete,
            lastChecked: Date.now(),
            data: {
              ...existingData,
              ...result.details
            }
          }
        }
      };
      setCareerWizardState(updatedState);
      await window.careerWizardAPI.setState(updatedState);

      return result;
    } catch (err: any) {
      console.error('Failed to validate step:', err);
      // Clear loading state on error
      setStepValidation(prev => {
        const current = prev.get(currentStep.id);
        return new Map(prev).set(currentStep.id, {
          ...current,
          isComplete: current?.isComplete ?? false,
          canProceed: current?.canProceed ?? false,
          isLoading: false
        });
      });
      throw err;
    }
  };

  const refreshStepStatus = async (stepId: string): Promise<void> => {
    try {
      // Set loading state
      setStepValidation(prev => {
        const current = prev.get(stepId);
        return new Map(prev).set(stepId, {
          ...current,
          isComplete: current?.isComplete ?? false,
          canProceed: current?.canProceed ?? false,
          isLoading: true
        });
      });

      const result = await window.careerWizardAPI.validateStep(stepId);
      setStepValidation(prev => new Map(prev).set(stepId, { ...result, isLoading: false }));

      // Reload fresh state from backend to avoid using stale React state
      const freshState = await window.careerWizardAPI.getState();
      const existingStepData = freshState.stepStatus[stepId];
      const existingData = existingStepData?.data || {};

      const updatedState: CareerSetupState = {
        ...freshState,
        stepStatus: {
          ...freshState.stepStatus,
          [stepId]: {
            completed: result.isComplete,
            lastChecked: Date.now(),
            data: {
              ...existingData,
              ...result.details
            }
          }
        }
      };
      setCareerWizardState(updatedState);
      await window.careerWizardAPI.setState(updatedState);

      // Note: Tray icon is updated when window gains focus or wizard completes
      // We don't update it here to avoid validating all steps on every refresh
    } catch (err: any) {
      console.error('Failed to refresh step status:', err);
      // Clear loading state on error
      setStepValidation(prev => {
        const current = prev.get(stepId);
        return new Map(prev).set(stepId, {
          ...current,
          isComplete: current?.isComplete ?? false,
          canProceed: current?.canProceed ?? false,
          isLoading: false
        });
      });
      throw err;
    }
  };

  const completeWizard = async (): Promise<void> => {
    try {
      // Validate all required steps
      for (const step of steps) {
        if (step.required) {
          const validation = stepValidation.get(step.id);
          if (!validation?.isComplete) {
            throw new Error(`Step "${step.title}" is not complete`);
          }
        }
      }

      // Mark career wizard as complete
      const updatedState: CareerSetupState = {
        ...careerWizardState!,
        completed: true
      };
      await window.careerWizardAPI.setState(updatedState);
      setCareerWizardState(updatedState);
    } catch (err: any) {
      console.error('Failed to complete careerWizard:', err);
      throw err;
    }
  };

  const dismissWizard = async (): Promise<void> => {
    try {
      const updatedState: CareerSetupState = {
        ...careerWizardState!,
        dismissedAt: Date.now()
      };
      await window.careerWizardAPI.setState(updatedState);
      setCareerWizardState(updatedState);
    } catch (err: any) {
      console.error('Failed to dismiss careerWizard:', err);
      throw err;
    }
  };

  const refreshAllSteps = async (): Promise<void> => {
    try {
      const startTime = performance.now();

      // Set all steps to loading
      const loadingValidations = new Map<string, StepValidationResult>();
      for (const step of steps) {
        loadingValidations.set(step.id, {
          isComplete: false,
          canProceed: false,
          isLoading: true
        });
      }
      setStepValidation(loadingValidations);

      console.log(`[Performance] Starting parallel refresh of ${steps.length} steps...`);

      // Validate all steps in parallel
      const validationPromises = steps.map(async (step) => {
        try {
          const result = await window.careerWizardAPI.validateStep(step.id);
          return { stepId: step.id, result: { ...result, isLoading: false }, error: null };
        } catch (err) {
          console.error(`Failed to validate step ${step.id}:`, err);
          return {
            stepId: step.id,
            result: {
              isComplete: false,
              canProceed: false,
              isLoading: false
            },
            error: err
          };
        }
      });

      // Wait for all validations to complete
      const results = await Promise.allSettled(validationPromises);

      // Process results and update state
      const finalValidations = new Map<string, StepValidationResult>();
      results.forEach((promiseResult) => {
        if (promiseResult.status === 'fulfilled') {
          const { stepId, result } = promiseResult.value;
          finalValidations.set(stepId, result);
        }
      });

      // Update all validations at once
      setStepValidation(finalValidations);

      const endTime = performance.now();
      const duration = Math.round(endTime - startTime);
      console.log(`[Performance] ✓ Parallel refresh completed in ${duration}ms`);
      console.log(`[Performance] Average per step: ${Math.round(duration / steps.length)}ms`);
    } catch (err: any) {
      console.error('Failed to refresh all steps:', err);
      throw err;
    }
  };

  const triggerRefresh = (): void => {
    setRefreshTrigger(prev => prev + 1);
  };

  const scrollToTop = (): void => {
    if (scrollContainerRef.current) {
      scrollContainerRef.current.scrollTo({ top: 0, behavior: 'smooth' });
    }
  };

  const value: CareerWizardContextType = {
    currentStepIndex,
    steps,
    stepValidation,
    loading,
    error,
    careerWizardState,
    refreshTrigger,
    scrollContainerRef,
    goToStep,
    nextStep,
    previousStep,
    validateCurrentStep,
    completeWizard,
    dismissWizard,
    refreshStepStatus,
    refreshAllSteps,
    triggerRefresh,
    scrollToTop
  };

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