"use client";

import { useEffect, useRef, useCallback, useState } from "react";
import { useCanvasStore } from "@/lib/store";
import { canvasDB } from "@/lib/db";
import { useAuth } from "@/components/auth";

interface UseAutoSaveOptions {
  debounceMs?: number;
  teamIdOverride?: string | null; // For admins viewing another team's canvas
  // When true, indicates admin is viewing another team - don't fall back to authTeamId
  isAdminContext?: boolean;
}

/**
 * Hook for auto-saving canvas data to Supabase
 * Debounces saves to prevent excessive writes
 * 
 * @param canvasId - The canvas template ID
 * @param options - Configuration options including optional teamId override for admins
 */
export function useAutoSave(canvasId: string, options: UseAutoSaveOptions = {}) {
  const { debounceMs = 1000, teamIdOverride, isAdminContext = false } = options;

  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
  const { getCanvas, hasUnsavedChanges, markAsSaved } = useCanvasStore();
  const { teamId: authTeamId } = useAuth();
  const [isSaving, setIsSaving] = useState(false);

  // For admin context: ONLY use teamIdOverride, never fall back to authTeamId
  // This prevents saving to the admin's own team when viewing another team's canvas
  // For regular users: use authTeamId as normal
  const effectiveTeamId = isAdminContext ? teamIdOverride : (teamIdOverride || authTeamId);

  const saveToDb = useCallback(async () => {
    if (!effectiveTeamId) {
      console.warn("[AutoSave] No team ID available, skipping save");
      return;
    }

    const canvas = getCanvas(canvasId);
    if (canvas) {
      try {
        setIsSaving(true);
        const success = await canvasDB.save(effectiveTeamId, canvasId, {
          fields: canvas.fields,
          elements: canvas.elements,
          metadata: canvas.metadata,
        });

        if (success) {
          markAsSaved();
          console.log(`[AutoSave] Saved canvas ${canvasId} to Supabase (team: ${effectiveTeamId})`);
        } else {
          console.error(`[AutoSave] Failed to save canvas ${canvasId}`);
        }
      } catch (error) {
        console.error(`[AutoSave] Failed to save canvas ${canvasId}:`, error);
      } finally {
        setIsSaving(false);
      }
    }
  }, [canvasId, getCanvas, markAsSaved, effectiveTeamId]);

  // Debounced save effect
  useEffect(() => {
    if (hasUnsavedChanges && effectiveTeamId) {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }

      timeoutRef.current = setTimeout(() => {
        saveToDb();
      }, debounceMs);
    }

    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, [hasUnsavedChanges, debounceMs, saveToDb, effectiveTeamId]);

  // Save on unmount if there are unsaved changes
  useEffect(() => {
    return () => {
      if (!effectiveTeamId) return;

      const canvas = getCanvas(canvasId);
      if (canvas && hasUnsavedChanges) {
        canvasDB.save(effectiveTeamId, canvasId, {
          fields: canvas.fields,
          elements: canvas.elements,
          metadata: canvas.metadata,
        }).catch(console.error);
      }
    };
  }, [canvasId, getCanvas, hasUnsavedChanges, effectiveTeamId]);

  // Force save when tab/window is closed (handles the debounce gap)
  // Also handle visibility change for mobile browsers
  useEffect(() => {
    const forceSave = () => {
      if (!effectiveTeamId || !hasUnsavedChanges) return;

      const canvas = getCanvas(canvasId);
      if (canvas) {
        // Trigger immediate save - the browser will try to complete this
        canvasDB.save(effectiveTeamId, canvasId, {
          fields: canvas.fields,
          elements: canvas.elements,
          metadata: canvas.metadata,
        }).catch(console.error);

        console.log(`[AutoSave] Force save triggered for canvas ${canvasId}`);
      }
    };

    const handleBeforeUnload = (e: BeforeUnloadEvent) => {
      if (hasUnsavedChanges) {
        forceSave();
        // Show browser's "unsaved changes" dialog as extra safety
        e.preventDefault();
        e.returnValue = '';
      }
    };

    // For mobile: save when app goes to background
    const handleVisibilityChange = () => {
      if (document.visibilityState === 'hidden' && hasUnsavedChanges) {
        forceSave();
      }
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    document.addEventListener('visibilitychange', handleVisibilityChange);

    return () => {
      window.removeEventListener('beforeunload', handleBeforeUnload);
      document.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, [canvasId, getCanvas, hasUnsavedChanges, effectiveTeamId]);

  return { saveNow: saveToDb, isSaving };
}

interface UseLoadCanvasOptions {
  teamIdOverride?: string | null; // For admins viewing another team's canvas
  // When true, indicates admin is viewing another team - don't fall back to authTeamId
  isAdminContext?: boolean;
}

/**
 * Hook to load canvas data from Supabase on mount
 * 
 * @param canvasId - The canvas template ID
 * @param options - Configuration options including optional teamId override for admins
 */
export function useLoadCanvas(canvasId: string, options: UseLoadCanvasOptions = {}) {
  const { teamIdOverride, isAdminContext = false } = options;

  const { setCanvasData, getCanvas, resetCanvas } = useCanvasStore();
  const { teamId: authTeamId } = useAuth();
  const [isLoading, setIsLoading] = useState(true);

  // Track which team's data we loaded - this lets us detect team changes
  const loadedTeamIdRef = useRef<string | null>(null);

  // For admin context: ONLY use teamIdOverride, never fall back to authTeamId
  // This prevents loading the admin's own team data when viewing another team's canvas
  // For regular users: use authTeamId as normal
  const effectiveTeamId = isAdminContext ? teamIdOverride : (teamIdOverride || authTeamId);

  useEffect(() => {
    async function loadFromDb() {
      if (!effectiveTeamId) {
        setIsLoading(false);
        return;
      }

      // Check if we've already loaded this team's data
      // If not, we need to clear the store and reload
      const alreadyLoaded = loadedTeamIdRef.current === effectiveTeamId;

      if (alreadyLoaded) {
        setIsLoading(false);
        return;
      }

      try {
        setIsLoading(true);

        // Clear the old canvas data first to prevent showing stale data from another team
        // This is crucial for admins switching between teams
        console.log(`[LoadCanvas] Loading canvas ${canvasId} for team ${effectiveTeamId} (previous: ${loadedTeamIdRef.current})`);

        const savedData = await canvasDB.get(effectiveTeamId, canvasId);

        if (savedData) {
          // Use setCanvasData to populate the store WITHOUT triggering hasUnsavedChanges
          // This prevents auto-save from immediately overwriting loaded data
          setCanvasData(canvasId, {
            fields: savedData.fields,
            elements: savedData.elements,
            metadata: savedData.metadata,
            updatedAt: Date.now(),
          });

          console.log(`[LoadCanvas] Loaded canvas ${canvasId} from Supabase (team: ${effectiveTeamId})`);
        } else {
          // No data for this team - clear the canvas to show empty state
          setCanvasData(canvasId, {
            fields: {},
            elements: [],
            metadata: {},
            updatedAt: Date.now(),
          });
          console.log(`[LoadCanvas] No saved data for canvas ${canvasId}, showing empty`);
        }

        // Mark this team as loaded
        loadedTeamIdRef.current = effectiveTeamId;
      } catch (error) {
        console.error(`[LoadCanvas] Failed to load canvas ${canvasId}:`, error);
      } finally {
        setIsLoading(false);
      }
    }

    loadFromDb();
    // NOTE: Only react to canvasId and effectiveTeamId changes
    // Do NOT include store functions (getCanvas, setCanvasData, resetCanvas) as they get 
    // recreated on every store update and would cause this effect to re-run unnecessarily
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [canvasId, effectiveTeamId]);

  const isLoaded = loadedTeamIdRef.current === effectiveTeamId;
  return { isLoading, isLoaded };
}

