import { useEffect, useRef, useState } from "react";
import { SidebarProvider, useSidebar } from "../context/SidebarContext";
import { Outlet } from "react-router";
import AppHeader from "./AppHeader";
import Backdrop from "./Backdrop";
import AppSidebar from "./AppSidebar";
import { useSiteStore } from "../store/siteStore";
import { useSectorStore } from "../store/sectorStore";
import { useAuthStore } from "../store/authStore";
import { useErrorHandler } from "../hooks/useErrorHandler";
import { trackLoading } from "../components/common/LoadingStateMonitor";
import ResourceDebugOverlay from "../components/debug/ResourceDebugOverlay";

const LayoutContent: React.FC = () => {
  const { isExpanded, isHovered, isMobileOpen } = useSidebar();
  const { loadActiveSite, activeSite } = useSiteStore();
  const { loadSectorsForSite } = useSectorStore();
  const { refreshUser, isAuthenticated } = useAuthStore();
  const { addError } = useErrorHandler('AppLayout');
  const hasLoadedSite = useRef(false);
  const lastSiteId = useRef<number | null>(null);
  const isLoadingSite = useRef(false);
  const isLoadingSector = useRef(false);
  const [debugEnabled, setDebugEnabled] = useState(false);
  const lastUserRefresh = useRef<number>(0);

  // Initialize site store on mount - only once, but only if authenticated
  useEffect(() => {
    // Only load sites if user is authenticated AND has a token
    if (!isAuthenticated) return;
    
    // Check if token exists - if not, wait a bit for Zustand persist to write it
    const checkTokenAndLoad = () => {
      const authState = useAuthStore.getState();
      if (!authState?.token) {
        // Token not available yet - wait a bit and retry (Zustand persist might still be writing)
        setTimeout(() => {
          const retryAuthState = useAuthStore.getState();
          if (retryAuthState?.token && !hasLoadedSite.current && !isLoadingSite.current) {
            loadSites();
          }
        }, 100); // Wait 100ms for persist to write
        return;
      }
      
      loadSites();
    };
    
    const loadSites = () => {
      if (!hasLoadedSite.current && !isLoadingSite.current) {
        hasLoadedSite.current = true;
        isLoadingSite.current = true;
        trackLoading('site-loading', true);
        
        // Add timeout to prevent infinite loading
        // Match API timeout (30s) + buffer for network delays
        const timeoutId = setTimeout(() => {
          if (isLoadingSite.current) {
            console.error('AppLayout: Site loading timeout after 35 seconds');
            trackLoading('site-loading', false);
            isLoadingSite.current = false;
            addError(new Error('Site loading timeout - check network connection'), 'AppLayout.loadActiveSite');
          }
        }, 35000); // 35 seconds to match API timeout (30s) + buffer
        
        loadActiveSite()
          .catch((error) => {
            // Don't log 403 errors as they're expected when not authenticated
            if (error.status !== 403) {
              console.error('AppLayout: Error loading active site:', error);
              addError(error, 'AppLayout.loadActiveSite');
            }
          })
          .finally(() => {
            clearTimeout(timeoutId);
            trackLoading('site-loading', false);
            isLoadingSite.current = false;
          });
      }
    };
    
    checkTokenAndLoad();
  }, [isAuthenticated]); // Run when authentication state changes

  // Load sectors when active site changes (by ID, not object reference)
  useEffect(() => {
    const currentSiteId = activeSite?.id ?? null;
    
    // Only load if:
    // 1. We have a site ID
    // 2. The site is active (inactive sites can't have accessible sectors)
    // 3. It's different from the last one we loaded
    // 4. We're not already loading
    if (currentSiteId && activeSite?.is_active && currentSiteId !== lastSiteId.current && !isLoadingSector.current) {
      lastSiteId.current = currentSiteId;
      isLoadingSector.current = true;
      trackLoading('sector-loading', true);
      
      // Add timeout to prevent infinite loading
      // Match API timeout (30s) + buffer for network delays
      const timeoutId = setTimeout(() => {
        if (isLoadingSector.current) {
          console.error('AppLayout: Sector loading timeout after 35 seconds');
          trackLoading('sector-loading', false);
          isLoadingSector.current = false;
          addError(new Error('Sector loading timeout - check network connection'), 'AppLayout.loadSectorsForSite');
        }
      }, 35000); // 35 seconds to match API timeout (30s) + buffer
      
      loadSectorsForSite(currentSiteId)
        .catch((error) => {
          // Don't log 403/404 errors as they're expected for inactive sites
          if (error.status !== 403 && error.status !== 404) {
            console.error('AppLayout: Error loading sectors:', error);
            addError(error, 'AppLayout.loadSectorsForSite');
          }
        })
        .finally(() => {
          clearTimeout(timeoutId);
          trackLoading('sector-loading', false);
          isLoadingSector.current = false;
        });
    } else if (currentSiteId && !activeSite?.is_active) {
      // Site is inactive - clear sectors and reset lastSiteId
      lastSiteId.current = null;
      const { useSectorStore } = require('../store/sectorStore');
      useSectorStore.getState().clearActiveSector();
    }
  }, [activeSite?.id, activeSite?.is_active]); // Depend on both ID and is_active

  // Refresh user data on mount and when app version changes (after code updates)
  // This ensures changes are reflected immediately without requiring re-login
  useEffect(() => {
    if (!isAuthenticated) return;
    
    const APP_VERSION = import.meta.env.VITE_APP_VERSION || '2.0.2';
    const VERSION_STORAGE_KEY = 'igny8-app-version';
    
    const refreshUserData = async (force = false) => {
      const now = Date.now();
      // Throttle: only refresh if last refresh was more than 30 seconds ago (unless forced)
      if (!force && now - lastUserRefresh.current < 30000) return;
      
      // Check if token exists before making API call
      const authState = useAuthStore.getState();
      if (!authState?.token) {
        // Token not available yet - wait a bit for Zustand persist to write it
        setTimeout(() => {
          const retryAuthState = useAuthStore.getState();
          if (retryAuthState?.token && retryAuthState?.isAuthenticated) {
            refreshUserData(force);
          }
        }, 100); // Wait 100ms for persist to write
        return;
      }
      
      try {
        lastUserRefresh.current = now;
        await refreshUser();
        
        // Store current version after successful refresh
        if (force) {
          localStorage.setItem(VERSION_STORAGE_KEY, APP_VERSION);
        }
      } catch (error) {
        // Silently fail - user might still be authenticated
        console.debug('User data refresh failed (non-critical):', error);
      }
    };
    
    // Check if app version changed (indicates code update)
    const storedVersion = localStorage.getItem(VERSION_STORAGE_KEY);
    if (storedVersion !== APP_VERSION) {
      // Force refresh on version change
      refreshUserData(true);
    } else {
      // Normal refresh on mount
      refreshUserData();
    }
    
    // Refresh when window becomes visible (user switches back to tab)
    const handleVisibilityChange = () => {
      if (document.visibilityState === 'visible') {
        refreshUserData();
      }
    };
    
    // Refresh on window focus
    const handleFocus = () => {
      refreshUserData();
    };
    
    // Periodic refresh every 2 minutes
    const intervalId = setInterval(() => refreshUserData(), 120000);
    
    document.addEventListener('visibilitychange', handleVisibilityChange);
    window.addEventListener('focus', handleFocus);
    
    return () => {
      clearInterval(intervalId);
      document.removeEventListener('visibilitychange', handleVisibilityChange);
      window.removeEventListener('focus', handleFocus);
    };
  }, [isAuthenticated, refreshUser]);

  // Listen for debug toggle changes
  useEffect(() => {
    const saved = localStorage.getItem('debug_resource_tracking_enabled');
    setDebugEnabled(saved === 'true');
    
    const handleToggle = (e: Event) => {
      const customEvent = e as CustomEvent;
      setDebugEnabled(customEvent.detail);
    };
    
    window.addEventListener('debug-resource-tracking-toggle', handleToggle);
    return () => {
      window.removeEventListener('debug-resource-tracking-toggle', handleToggle);
    };
  }, []);

  return (
    <div className="min-h-screen xl:flex">
      <div>
        <AppSidebar />
        <Backdrop />
      </div>
      <div
        className={`flex-1 transition-all duration-300 ease-in-out ${
          isExpanded || isHovered ? "lg:ml-[290px]" : "lg:ml-[90px]"
        } ${isMobileOpen ? "ml-0" : ""} w-full max-w-full min-[1440px]:max-w-[90%]`}
      >
        <AppHeader />
        <div className="p-4 pb-20 md:p-6 md:pb-24">
          <Outlet />
        </div>
        {/* Resource Debug Overlay - Only visible when enabled by admin */}
        <ResourceDebugOverlay enabled={debugEnabled} />
      </div>
    </div>
  );
};

const AppLayout: React.FC = () => {
  return (
    <SidebarProvider>
      <LayoutContent />
    </SidebarProvider>
  );
};

export default AppLayout;
