'use client';

import React, { FC, ReactNode, createContext, useContext, useEffect, useState, useCallback } from 'react';
import { ClientOnline } from '@/types/mutual/context/validations';
import { checkContextPageOnline, setContextPageOnline } from './context';
import { setOnlineToRedis } from '@/apifetchers/mutual/context/page/online/fetch';

// Default online state to use as fallback
const DEFAULT_ONLINE_STATE: ClientOnline = {
  lang: "en",
  userType: "occupant",
  lastLogin: new Date(),
  lastLogout: new Date(),
  lastAction: new Date(),
  lastPage: "/auth/login",
  timezone: "GMT+3"
};

// Create context with default values
interface OnlineContextType {
  online: ClientOnline | null;
  updateOnline: (newOnline: ClientOnline) => Promise<boolean>;
  isLoading: boolean;
  error: string | null;
  retryFetch: () => Promise<void>;
}

const OnlineContext = createContext<OnlineContextType>({
  online: null,
  updateOnline: async () => false,
  isLoading: false,
  error: null,
  retryFetch: async () => {}
});

// Custom hook to use the context
export const useOnline = () => useContext(OnlineContext);

// Provider component
interface OnlineProviderProps {
  children: ReactNode;
}

export const OnlineProvider: FC<OnlineProviderProps> = ({ children }) => {
  const [online, setOnline] = useState<ClientOnline | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);
  const [retryCount, setRetryCount] = useState<number>(0);
  const [lastRetryTime, setLastRetryTime] = useState<number>(0);

  // Maximum number of automatic retries
  const MAX_AUTO_RETRIES = 3;
  // Minimum time between retries in milliseconds (5 seconds)
  const MIN_RETRY_INTERVAL = 5000;

  // Function to fetch online state
  const fetchOnline = useCallback(async (force = false) => {
    // Don't fetch if we already have data and it's not forced
    if (online && !force && !error) {
      console.log("Using existing online state:", online);
      return;
    }

    // Don't retry too frequently
    const now = Date.now();
    if (!force && now - lastRetryTime < MIN_RETRY_INTERVAL) {
      console.log("Retry attempted too soon, skipping");
      return;
    }

    setIsLoading(true);
    setError(null);
    setLastRetryTime(now);

    try {
      console.log("Fetching online state...");
      const data = await checkContextPageOnline();
      
      if (data) {
        console.log("Successfully fetched online state:", data);
        setOnline(data);
        setRetryCount(0); // Reset retry count on success
      } else {
        console.warn("No online state returned, using default");
        setOnline(DEFAULT_ONLINE_STATE);
        setError("Could not retrieve online state, using default values");
        
        // Auto-retry if under the limit
        if (retryCount < MAX_AUTO_RETRIES) {
          setRetryCount(prev => prev + 1);
          console.log(`Scheduling retry ${retryCount + 1}/${MAX_AUTO_RETRIES}...`);
          setTimeout(() => fetchOnline(true), MIN_RETRY_INTERVAL);
        }
      }
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      console.error("Error fetching online state:", errorMessage);
      setError(`Failed to fetch online state: ${errorMessage}`);
      setOnline(DEFAULT_ONLINE_STATE); // Use default as fallback
      
      // Auto-retry if under the limit
      if (retryCount < MAX_AUTO_RETRIES) {
        setRetryCount(prev => prev + 1);
        console.log(`Scheduling retry ${retryCount + 1}/${MAX_AUTO_RETRIES}...`);
        setTimeout(() => fetchOnline(true), MIN_RETRY_INTERVAL);
      }
    } finally {
      setIsLoading(false);
    }
  }, [online, error, retryCount, lastRetryTime]);

  // Manual retry function that can be called from components
  const retryFetch = useCallback(async () => {
    console.log("Manual retry requested");
    setRetryCount(0); // Reset retry count for manual retry
    await fetchOnline(true);
  }, [fetchOnline]);

  // Fetch online state on component mount
  useEffect(() => {
    console.log("OnlineProvider mounted, fetching initial data");
    
    // Always fetch data on mount
    fetchOnline();
    
    // Set up periodic refresh (every 5 minutes)
    const refreshInterval = setInterval(() => {
      console.log("Performing periodic refresh of online state");
      fetchOnline(true);
    }, 5 * 60 * 1000);
    
    return () => {
      console.log("OnlineProvider unmounted, clearing interval");
      clearInterval(refreshInterval);
    };
  }, [fetchOnline]);

  // Function to update online state
  const updateOnline = async (newOnline: ClientOnline): Promise<boolean> => {
    setIsLoading(true);
    setError(null);
    
    try {
      console.log("Updating online state:", newOnline);
      // Update Redis first
      console.log('Updating Redis...');
      await setOnlineToRedis(newOnline);
      
      // Then update context API
      console.log('Updating context API...');
      await setContextPageOnline(newOnline);
      
      // Finally update local state to trigger re-renders
      console.log('Updating local state...');
      setOnline(newOnline);
      
      console.log('Online state updated successfully');
      return true;
    } catch (error) {
      console.error('Error updating online state:', error);
      
      // Still update local state to maintain UI consistency
      // even if the backend updates failed
      setOnline(newOnline);
      
      return false;
    } finally {
      setIsLoading(false);
    }
  };

  // Add debug logging for provider state
  useEffect(() => {
    console.log('OnlineProvider state updated:', { 
      online: online ? 'present' : 'not present', 
      isLoading 
    });
  }, [online, isLoading]);

  return (
    <OnlineContext.Provider value={{ online, updateOnline, isLoading, error, retryFetch }}>
      {children}
    </OnlineContext.Provider>
  );
};

// Export as default for backward compatibility
export default OnlineProvider;
