import React, { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react';
import * as Types from 'types/types';
// Assuming you're using React Router
import { useLocation, useNavigate } from 'react-router-dom';
import { useAuth } from 'hooks/AuthContext';
import { SetSnackType, SeverityType, Snack } from 'components/Snack';

// ============================
// Storage Keys
// ============================

const STORAGE_KEYS = {
  SELECTED_CANDIDATE_ID: 'selectedCandidateId',
  SELECTED_JOB_ID: 'selectedJobId',
  SELECTED_EMPLOYER_ID: 'selectedEmployerId',
  LAST_ROUTE: 'lastVisitedRoute',
  ROUTE_STATE: 'routeState',
  ACTIVE_TAB: 'activeTab',
  APPLIED_FILTERS: 'appliedFilters',
  SIDEBAR_COLLAPSED: 'sidebarCollapsed'
} as const;

// ============================
// Route State Interface
// ============================

interface RouteState {
  lastRoute: string | null;
  activeTab: string | null;
  appliedFilters: Record<string, any>;
  sidebarCollapsed: boolean;
}

// ============================
// Enhanced App State Interface
// ============================

export interface AppState {
  selectedCandidate: Types.Candidate | null;
  selectedJob: Types.Job | null;
  selectedEmployer: Types.Employer | null;
  routeState: RouteState;
  isInitializing: boolean;
}

export interface AppStateActions {
  // Snackbar
  setSnack: SetSnackType;

  //
  setSelectedCandidate: (candidate: Types.Candidate | null) => void;
  setSelectedJob: (job: Types.Job | null) => void;
  setSelectedEmployer: (employer: Types.Employer | null) => void;
  clearSelections: () => void;

  // Route management
  saveCurrentRoute: () => void;
  restoreLastRoute: () => void;
  setActiveTab: (tab: string) => void;
  setFilters: (filters: Record<string, any>) => void;
  setSidebarCollapsed: (collapsed: boolean) => void;
  clearRouteState: () => void;
}

export type AppStateContextType = AppState & AppStateActions;

// ============================
// Storage Utilities
// ============================

function getStoredId(key: string): string | null {
  try {
    return localStorage.getItem(key);
  } catch (error) {
    console.warn('Failed to read from localStorage:', error);
    return null;
  }
}

function setStoredId(key: string, id: string | null): void {
  try {
    if (id) {
      localStorage.setItem(key, id);
    } else {
      localStorage.removeItem(key);
    }
  } catch (error) {
    console.warn('Failed to write to localStorage:', error);
  }
}

function getStoredObject<T>(key: string, defaultValue: T): T {
  try {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : defaultValue;
  } catch (error) {
    console.warn(`Failed to read ${key} from localStorage:`, error);
    return defaultValue;
  }
}

function setStoredObject(key: string, value: any): void {
  try {
    localStorage.setItem(key, JSON.stringify(value));
  } catch (error) {
    console.warn(`Failed to write ${key} to localStorage:`, error);
  }
}

// ============================
// Route State Management
// ============================

function getInitialRouteState(): RouteState {
  return {
    lastRoute: getStoredId(STORAGE_KEYS.LAST_ROUTE),
    activeTab: getStoredId(STORAGE_KEYS.ACTIVE_TAB),
    appliedFilters: getStoredObject(STORAGE_KEYS.APPLIED_FILTERS, {}),
    sidebarCollapsed: getStoredObject(STORAGE_KEYS.SIDEBAR_COLLAPSED, false)
  };
}

function persistRouteState(routeState: RouteState): void {
  setStoredId(STORAGE_KEYS.LAST_ROUTE, routeState.lastRoute);
  setStoredId(STORAGE_KEYS.ACTIVE_TAB, routeState.activeTab);
  setStoredObject(STORAGE_KEYS.APPLIED_FILTERS, routeState.appliedFilters);
  setStoredObject(STORAGE_KEYS.SIDEBAR_COLLAPSED, routeState.sidebarCollapsed);
}

// ============================
// Enhanced App State Hook
// ============================

export function useAppStateLogic(): AppStateContextType {
  const location = useLocation();
  const navigate = useNavigate();
  const { apiClient } = useAuth();

  // Entity state
  const [selectedCandidate, setSelectedCandidateState] = useState<Types.Candidate | null>(null);
  const [selectedJob, setSelectedJobState] = useState<Types.Job | null>(null);
  const [selectedEmployer, setSelectedEmployerState] = useState<Types.Employer | null>(null);
  const [isInitializing, setIsInitializing] = useState<boolean>(true);

  // Route state
  const [routeState, setRouteStateState] = useState<RouteState>(getInitialRouteState);

  // ============================
  // Initialization Effect
  // ============================

  useEffect(() => {
    const initializeFromStorage = async () => {
      setIsInitializing(true);

      try {
        // Get stored entity IDs
        const candidateId = getStoredId(STORAGE_KEYS.SELECTED_CANDIDATE_ID);
        const jobId = getStoredId(STORAGE_KEYS.SELECTED_JOB_ID);
        const employerId = getStoredId(STORAGE_KEYS.SELECTED_EMPLOYER_ID);

        // Restore entities in parallel if IDs exist
        const promises: Promise<void>[] = [];

        if (candidateId) {
          promises.push(
            (async () => {
              try {
                const candidate = await apiClient.getCandidate(candidateId);
                if (candidate) {
                  setSelectedCandidateState(candidate);
                  console.log('Restored candidate from storage:', candidate);
                } else {
                  setStoredId(STORAGE_KEYS.SELECTED_CANDIDATE_ID, null);
                  console.log('Candidate not found, cleared from storage');
                }
              } catch (error) {
                console.warn('Failed to restore candidate:', error);
                setStoredId(STORAGE_KEYS.SELECTED_CANDIDATE_ID, null);
              }
            })()
          );
        }

        if (jobId) {
          promises.push(
            (async () => {
              try {
                const job = await apiClient.getJob(jobId);
                if (job) {
                  setSelectedJobState(job);
                  console.log('Restored job from storage:', job);
                } else {
                  setStoredId(STORAGE_KEYS.SELECTED_JOB_ID, null);
                  console.log('Job not found, cleared from storage');
                }
              } catch (error) {
                console.warn('Failed to restore job:', error);
                setStoredId(STORAGE_KEYS.SELECTED_JOB_ID, null);
              }
            })()
          );
        }

        if (employerId) {
          promises.push(
            (async () => {
              try {
                const employer = await apiClient.getEmployer(employerId);
                if (employer) {
                  setSelectedEmployerState(employer);
                  console.log('Restored employer from storage:', employer);
                } else {
                  setStoredId(STORAGE_KEYS.SELECTED_EMPLOYER_ID, null);
                  console.log('Employer not found, cleared from storage');
                }
              } catch (error) {
                console.warn('Failed to restore employer:', error);
                setStoredId(STORAGE_KEYS.SELECTED_EMPLOYER_ID, null);
              }
            })()
          );
        }

        // Wait for all restoration attempts to complete
        await Promise.all(promises);

      } catch (error) {
        console.error('Error during app state initialization:', error);
      } finally {
        setIsInitializing(false);
      }
    };

    initializeFromStorage();
  }, []);

  // ============================
  // Auto-save current route
  // ============================

  useEffect(() => {
    // Don't save certain routes (login, register, etc.)
    const excludedRoutes = ['/login', '/register', '/verify-email', '/reset-password'];
    const shouldSaveRoute = !excludedRoutes.some(route => location.pathname.startsWith(route));

    if (shouldSaveRoute && !isInitializing) {
      setRouteStateState(prev => {
        const newState = { ...prev, lastRoute: location.pathname };
        persistRouteState(newState);
        return newState;
      });
    }
  }, [location.pathname, isInitializing]);

  // ============================
  // Entity State Setters with Persistence
  // ============================

  const setSelectedCandidate = useCallback((candidate: Types.Candidate | null) => {
    setSelectedCandidateState(candidate);
    setStoredId(STORAGE_KEYS.SELECTED_CANDIDATE_ID, candidate?.id || null);

    if (candidate) {
      console.log('Selected candidate:', candidate);
    } else {
      console.log('Cleared selected candidate');
    }
  }, []);

  const setSelectedJob = useCallback((job: Types.Job | null) => {
    setSelectedJobState(job);
    setStoredId(STORAGE_KEYS.SELECTED_JOB_ID, job?.id || null);

    if (job) {
      console.log('Selected job:', job);
    } else {
      console.log('Cleared selected job');
    }
  }, []);

  const setSelectedEmployer = useCallback((employer: Types.Employer | null) => {
    setSelectedEmployerState(employer);
    setStoredId(STORAGE_KEYS.SELECTED_EMPLOYER_ID, employer?.id || null);

    if (employer) {
      console.log('Selected employer:', employer);
    } else {
      console.log('Cleared selected employer');
    }
  }, []);

  const clearSelections = useCallback(() => {
    setSelectedCandidateState(null);
    setSelectedJobState(null);
    setSelectedEmployerState(null);

    setStoredId(STORAGE_KEYS.SELECTED_CANDIDATE_ID, null);
    setStoredId(STORAGE_KEYS.SELECTED_JOB_ID, null);
    setStoredId(STORAGE_KEYS.SELECTED_EMPLOYER_ID, null);

    console.log('Cleared all selections');
  }, []);

  // ============================
  // Route State Actions
  // ============================

  const saveCurrentRoute = useCallback(() => {
    setRouteStateState(prev => {
      const newState = { ...prev, lastRoute: location.pathname };
      persistRouteState(newState);
      return newState;
    });
  }, [location.pathname]);

  const restoreLastRoute = useCallback(() => {
    if (routeState.lastRoute && routeState.lastRoute !== location.pathname) {
      navigate(routeState.lastRoute);
    }
  }, [routeState.lastRoute, location.pathname, navigate]);

  const setActiveTab = useCallback((tab: string) => {
    setRouteStateState(prev => {
      const newState = { ...prev, activeTab: tab };
      persistRouteState(newState);
      return newState;
    });
  }, []);

  const setFilters = useCallback((filters: Record<string, any>) => {
    setRouteStateState(prev => {
      const newState = { ...prev, appliedFilters: filters };
      persistRouteState(newState);
      return newState;
    });
  }, []);

  const setSidebarCollapsed = useCallback((collapsed: boolean) => {
    setRouteStateState(prev => {
      const newState = { ...prev, sidebarCollapsed: collapsed };
      persistRouteState(newState);
      return newState;
    });
  }, []);

  const clearRouteState = useCallback(() => {
    const clearedState: RouteState = {
      lastRoute: null,
      activeTab: null,
      appliedFilters: {},
      sidebarCollapsed: false
    };

    setRouteStateState(clearedState);

    // Clear from localStorage
    localStorage.removeItem(STORAGE_KEYS.LAST_ROUTE);
    localStorage.removeItem(STORAGE_KEYS.ACTIVE_TAB);
    localStorage.removeItem(STORAGE_KEYS.APPLIED_FILTERS);
    localStorage.removeItem(STORAGE_KEYS.SIDEBAR_COLLAPSED);

    console.log('Cleared all route state');
  }, []);

  const emptySetSnack: SetSnackType = (message: string, severity?: SeverityType) => {
    return;
  };

  return {
    setSnack: emptySetSnack,
    selectedCandidate,
    selectedJob,
    selectedEmployer,
    routeState,
    isInitializing,
    setSelectedCandidate,
    setSelectedJob,
    setSelectedEmployer,
    clearSelections,
    saveCurrentRoute,
    restoreLastRoute,
    setActiveTab,
    setFilters,
    setSidebarCollapsed,
    clearRouteState
  };
}

// ============================
// Context Provider
// ============================

const AppStateContext = createContext<AppStateContextType | null>(null);

export function AppStateProvider({ children }: { children: React.ReactNode }) {
  const appState = useAppStateLogic();
  const snackRef = useRef<any>(null);

  // Global UI components
  appState.setSnack = useCallback((message: string, severity?: SeverityType) => {
    snackRef.current?.setSnack(message, severity);
  }, [snackRef]);
  
  return (
    <AppStateContext.Provider value={appState}>
      {children}
      <Snack ref={snackRef} />
    </AppStateContext.Provider>
  );
}

export function useAppState() {
  const context = useContext(AppStateContext);
  if (!context) {
    throw new Error('useAppState must be used within an AppStateProvider');
  }
  return context;
}

// ============================
// Convenience Hooks
// ============================

export function useSelectedCandidate() {
  const { selectedCandidate, setSelectedCandidate } = useAppState();
  return { selectedCandidate, setSelectedCandidate };
}

export function useSelectedJob() {
  const { selectedJob, setSelectedJob } = useAppState();
  return { selectedJob, setSelectedJob };
}

export function useSelectedEmployer() {
  const { selectedEmployer, setSelectedEmployer } = useAppState();
  return { selectedEmployer, setSelectedEmployer };
}

export function useRouteState() {
  const {
    routeState,
    setActiveTab,
    setFilters,
    setSidebarCollapsed,
    restoreLastRoute,
    clearRouteState
  } = useAppState();

  return {
    routeState,
    setActiveTab,
    setFilters,
    setSidebarCollapsed,
    restoreLastRoute,
    clearRouteState
  };
}

export function useAppInitializing() {
  const { isInitializing } = useAppState();
  return isInitializing;
}