import React, { createContext, useContext, useReducer, useCallback, useEffect } from 'react';
import type { CheckoutPackage, CheckoutStepId } from './types';

interface CheckoutState {
  currentStep: CheckoutStepId;
  selectedPackage: CheckoutPackage | null;
  packageOptions: CheckoutPackage[];
  authUser: unknown;
  isAuthenticated: boolean;
  paymentIntent: string | null;
  loading: boolean;
  error: string | null;
  paymentCompleted: boolean;
  checkoutSessionId: string | null;
}

interface CheckoutWizardContextType {
  state: CheckoutState;
  selectedPackage: CheckoutPackage | null;
  packageOptions: CheckoutPackage[];
  currentStep: CheckoutStepId;
  isAuthenticated: boolean;
  authUser: unknown;
  paddleConfig?: {
    environment?: string | null;
    client_token?: string | null;
  } | null;
  paymentCompleted: boolean;
  checkoutSessionId: string | null;
  selectPackage: (pkg: CheckoutPackage) => void;
  setSelectedPackage: (pkg: CheckoutPackage) => void;
  setAuthUser: (user: unknown) => void;
  nextStep: () => void;
  prevStep: () => void;
  previousStep: () => void;
  goToStep: (step: CheckoutStepId) => void;
  cancelCheckout: () => void;
  updatePaymentIntent: (clientSecret: string | null) => void;
  setLoading: (loading: boolean) => void;
  setError: (error: string | null) => void;
  resetPaymentState: () => void;
  setPaymentCompleted: (completed: boolean) => void;
  setCheckoutSessionId: (sessionId: string | null) => void;
  clearCheckoutSessionId: () => void;
}

const CheckoutWizardContext = createContext<CheckoutWizardContextType | null>(null);

const initialState: CheckoutState = {
  currentStep: 'package',
  selectedPackage: null,
  packageOptions: [],
  authUser: null,
  isAuthenticated: false,
  paymentIntent: null,
  loading: false,
  error: null,
  paymentCompleted: false,
  checkoutSessionId: null,
};

type CheckoutAction =
  | { type: 'SELECT_PACKAGE'; payload: CheckoutPackage }
  | { type: 'SET_AUTH_USER'; payload: unknown }
  | { type: 'NEXT_STEP' }
  | { type: 'PREV_STEP' }
  | { type: 'GO_TO_STEP'; payload: CheckoutStepId }
  | { type: 'UPDATE_PAYMENT_INTENT'; payload: string | null }
  | { type: 'SET_LOADING'; payload: boolean }
  | { type: 'SET_ERROR'; payload: string | null }
  | { type: 'SET_PAYMENT_COMPLETED'; payload: boolean }
  | { type: 'SET_CHECKOUT_SESSION_ID'; payload: string | null };

function checkoutReducer(state: CheckoutState, action: CheckoutAction): CheckoutState {
  switch (action.type) {
    case 'SELECT_PACKAGE':
      return { ...state, selectedPackage: action.payload, paymentCompleted: false };
    case 'SET_AUTH_USER':
      return { ...state, authUser: action.payload, isAuthenticated: Boolean(action.payload) };
    case 'NEXT_STEP':
      {
        const steps: CheckoutStepId[] = ['package', 'auth', 'payment', 'confirmation'];
        const currentIndex = steps.indexOf(state.currentStep);
        if (currentIndex < steps.length - 1) {
          return { ...state, currentStep: steps[currentIndex + 1] };
        }
        return state;
      }
    case 'PREV_STEP':
      {
        const prevSteps: CheckoutStepId[] = ['package', 'auth', 'payment', 'confirmation'];
        const prevIndex = prevSteps.indexOf(state.currentStep);
        if (prevIndex > 0) {
          return { ...state, currentStep: prevSteps[prevIndex - 1] };
        }
        return state;
      }
    case 'GO_TO_STEP':
      return { ...state, currentStep: action.payload };
    case 'UPDATE_PAYMENT_INTENT':
      return { ...state, paymentIntent: action.payload };
    case 'SET_LOADING':
      return { ...state, loading: action.payload };
    case 'SET_ERROR':
      return { ...state, error: action.payload };
    case 'SET_PAYMENT_COMPLETED':
      return { ...state, paymentCompleted: action.payload };
    case 'SET_CHECKOUT_SESSION_ID':
      return { ...state, checkoutSessionId: action.payload };
    default:
      return state;
  }
}

interface CheckoutWizardProviderProps {
  children: React.ReactNode;
  initialPackage?: CheckoutPackage;
  packageOptions?: CheckoutPackage[];
  initialStep?: CheckoutStepId;
  initialAuthUser?: unknown;
  initialIsAuthenticated?: boolean;
  paddle?: {
    environment?: string | null;
    client_token?: string | null;
  } | null;
}

export function CheckoutWizardProvider({
  children,
  initialPackage,
  packageOptions,
  initialStep,
  initialAuthUser,
  initialIsAuthenticated,
  paddle,
}: CheckoutWizardProviderProps) {
  const customInitialState: CheckoutState = {
    ...initialState,
    currentStep: initialStep || 'package',
    selectedPackage: initialPackage || null,
    packageOptions: packageOptions || [],
    authUser: initialAuthUser || null,
    isAuthenticated: initialIsAuthenticated || Boolean(initialAuthUser),
  };

  const checkoutSessionStorageKey = 'checkout-session-id';

  const [state, dispatch] = useReducer(checkoutReducer, customInitialState);

  // Load state from localStorage on mount
  useEffect(() => {
    const savedState = localStorage.getItem('checkout-wizard-state');
    if (savedState) {
      try {
        const parsed = JSON.parse(savedState);
        const hasValidPackage = parsed.selectedPackage && typeof parsed.selectedPackage.paddle_price_id === 'string' && parsed.selectedPackage.paddle_price_id !== '';
        if (hasValidPackage && initialPackage && parsed.selectedPackage.id === initialPackage.id && parsed.currentStep !== 'confirmation') {
          // Restore state selectively
          if (parsed.selectedPackage) dispatch({ type: 'SELECT_PACKAGE', payload: parsed.selectedPackage });
          if (parsed.currentStep) dispatch({ type: 'GO_TO_STEP', payload: parsed.currentStep });
        } else {
          localStorage.removeItem('checkout-wizard-state');
      }
    } catch (error) {
      console.error('Failed to restore checkout state:', error);
    }
  }

    const storedSession = localStorage.getItem(checkoutSessionStorageKey);
    if (storedSession) {
      dispatch({ type: 'SET_CHECKOUT_SESSION_ID', payload: storedSession });
    }
  }, [initialPackage]);

  // Save state to localStorage whenever it changes
  useEffect(() => {
    localStorage.setItem('checkout-wizard-state', JSON.stringify({
      selectedPackage: state.selectedPackage,
      currentStep: state.currentStep,
    }));
  }, [state.selectedPackage, state.currentStep]);

  // Clear localStorage when confirmation step is reached
  useEffect(() => {
    if (state.currentStep === 'confirmation') {
      localStorage.removeItem('checkout-wizard-state');
    }
  }, [state.currentStep]);

  useEffect(() => {
    if (state.checkoutSessionId) {
      localStorage.setItem(checkoutSessionStorageKey, state.checkoutSessionId);
    } else {
      localStorage.removeItem(checkoutSessionStorageKey);
    }
  }, [state.checkoutSessionId]);

  const selectPackage = useCallback((pkg: CheckoutPackage) => {
    dispatch({ type: 'SELECT_PACKAGE', payload: pkg });
  }, []);

  const setAuthUser = useCallback((user: unknown) => {
    dispatch({ type: 'SET_AUTH_USER', payload: user });
  }, []);

  const nextStep = useCallback(() => {
    dispatch({ type: 'NEXT_STEP' });
  }, []);

  const prevStep = useCallback(() => {
    dispatch({ type: 'PREV_STEP' });
  }, []);

  const goToStep = useCallback((step: CheckoutStepId) => {
    dispatch({ type: 'GO_TO_STEP', payload: step });
  }, []);

  const updatePaymentIntent = useCallback((clientSecret: string | null) => {
    dispatch({ type: 'UPDATE_PAYMENT_INTENT', payload: clientSecret });
  }, []);

  const setLoading = useCallback((loading: boolean) => {
    dispatch({ type: 'SET_LOADING', payload: loading });
  }, []);

  const setError = useCallback((error: string | null) => {
    dispatch({ type: 'SET_ERROR', payload: error });
  }, []);

  const setSelectedPackage = useCallback((pkg: CheckoutPackage) => {
    dispatch({ type: 'SELECT_PACKAGE', payload: pkg });
  }, []);

  const resetPaymentState = useCallback(() => {
    dispatch({ type: 'UPDATE_PAYMENT_INTENT', payload: null });
    dispatch({ type: 'SET_LOADING', payload: false });
    dispatch({ type: 'SET_ERROR', payload: null });
    dispatch({ type: 'SET_PAYMENT_COMPLETED', payload: false });
    dispatch({ type: 'SET_CHECKOUT_SESSION_ID', payload: null });
  }, []);

  const setPaymentCompleted = useCallback((completed: boolean) => {
    dispatch({ type: 'SET_PAYMENT_COMPLETED', payload: completed });
  }, []);

  const setCheckoutSessionId = useCallback((sessionId: string | null) => {
    dispatch({ type: 'SET_CHECKOUT_SESSION_ID', payload: sessionId });
  }, []);

  const clearCheckoutSessionId = useCallback(() => {
    dispatch({ type: 'SET_CHECKOUT_SESSION_ID', payload: null });
  }, []);

  const cancelCheckout = useCallback(() => {
    // Track abandoned checkout (fire and forget)
    if (state.authUser || state.selectedPackage) {
      fetch('/checkout/track-abandoned', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
        },
        body: JSON.stringify({
          package_id: state.selectedPackage?.id,
          step: state.currentStep,
          email: state.authUser?.email,
        }),
      }).catch(error => {
        console.error('Failed to track abandoned checkout:', error);
      });
    }

    // State aus localStorage entfernen
    localStorage.removeItem('checkout-wizard-state');
    localStorage.removeItem(checkoutSessionStorageKey);
    // Zur Package-Übersicht zurückleiten
    window.location.href = '/packages';
  }, [state, checkoutSessionStorageKey]);

  const value: CheckoutWizardContextType = {
    state,
    selectedPackage: state.selectedPackage,
    packageOptions: state.packageOptions,
    currentStep: state.currentStep,
    isAuthenticated: state.isAuthenticated,
    authUser: state.authUser,
    paddleConfig: paddle ?? null,
    paymentCompleted: state.paymentCompleted,
    checkoutSessionId: state.checkoutSessionId,
    selectPackage,
    setSelectedPackage,
    setAuthUser,
    nextStep,
    prevStep,
    previousStep: prevStep,
    goToStep,
    cancelCheckout,
    updatePaymentIntent,
    setLoading,
    setError,
    resetPaymentState,
    setPaymentCompleted,
    setCheckoutSessionId,
    clearCheckoutSessionId,
  };

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

export function useCheckoutWizard(): CheckoutWizardContextType {
  const context = useContext(CheckoutWizardContext);
  if (!context) {
    throw new Error('useCheckoutWizard must be used within a CheckoutWizardProvider');
  }
  return context;
}
