import { useEffect, useRef, useState, useCallback } from 'react';
import { useToast } from '@chakra-ui/react';

export type SaveStatus = 'idle' | 'saving' | 'saved' | 'error';

interface UseAutoSaveOptions<T> {
  data: T;
  storageKey: string;
  onSave: (data: T) => Promise<{ id?: number | string; [key: string]: any }>;
  onError?: (error: any) => void;
  debounceMs?: number;
  enabled?: boolean;
  requiresId?: boolean; // If true, only saves to backend when item has an ID
}

interface UseAutoSaveReturn {
  saveStatus: SaveStatus;
  lastSaved: Date | null;
  forceSave: () => Promise<void>;
  clearDraft: () => void;
  hasDraft: boolean;
  draftAge: number | null; // Age in minutes
}

/**
 * Auto-save hook with dual-layer protection:
 * 1. Immediate localStorage save for offline protection
 * 2. Debounced backend save for persistence
 * 
 * Usage:
 * ```tsx
 * const { saveStatus, lastSaved, forceSave, clearDraft } = useAutoSave({
 *   data: formData,
 *   storageKey: 'draft-article-123',
 *   onSave: async (data) => {
 *     if (data.id) {
 *       return await updateArticle(data.id, data);
 *     } else {
 *       return await createArticle({ ...data, published: false });
 *     }
 *   },
 *   debounceMs: 2000,
 *   enabled: true
 * });
 * ```
 */
export function useAutoSave<T extends Record<string, any>>({
  data,
  storageKey,
  onSave,
  onError,
  debounceMs = 2000,
  enabled = true,
  requiresId = false,
}: UseAutoSaveOptions<T>): UseAutoSaveReturn {
  const toast = useToast();
  const [saveStatus, setSaveStatus] = useState<SaveStatus>('idle');
  const [lastSaved, setLastSaved] = useState<Date | null>(null);
  const [hasDraft, setHasDraft] = useState(false);
  const [draftAge, setDraftAge] = useState<number | null>(null);
  
  const saveTimerRef = useRef<NodeJS.Timeout>();
  const lastDataRef = useRef<string>('');
  const isSavingRef = useRef(false);

  // Check for existing draft on mount
  useEffect(() => {
    try {
      const stored = localStorage.getItem(storageKey);
      if (stored) {
        const parsed = JSON.parse(stored);
        setHasDraft(true);
        if (parsed.timestamp) {
          const age = Math.floor((Date.now() - parsed.timestamp) / 60000); // minutes
          setDraftAge(age);
        }
      }
    } catch (err) {
      console.warn('Failed to check for draft:', err);
    }
  }, [storageKey]);

  // Save to localStorage immediately (instant protection)
  const saveToLocalStorage = useCallback((data: T) => {
    try {
      const payload = {
        data,
        timestamp: Date.now(),
        version: 1,
      };
      localStorage.setItem(storageKey, JSON.stringify(payload));
      setHasDraft(true);
      setDraftAge(0);
    } catch (err) {
      console.error('Failed to save to localStorage:', err);
    }
  }, [storageKey]);

  // Save to backend (debounced)
  const saveToBackend = useCallback(async (data: T) => {
    // If requiresId is true and no ID exists, skip backend save
    if (requiresId && !data.id) {
      console.log('Skipping backend save - no ID yet');
      return;
    }

    if (isSavingRef.current) {
      console.log('Save already in progress, skipping...');
      return;
    }

    try {
      isSavingRef.current = true;
      setSaveStatus('saving');
      
      const result = await onSave(data);
      
      setSaveStatus('saved');
      setLastSaved(new Date());
      
      // If the save returned an ID, update the data reference
      if (result?.id && !data.id) {
        console.log('Draft saved with new ID:', result.id);
      }
      
      setTimeout(() => setSaveStatus('idle'), 2000);
    } catch (error: any) {
      console.error('Auto-save error:', error);
      setSaveStatus('error');
      
      if (onError) {
        onError(error);
      } else {
        // Only show error toast if it's not a 401/403 (auth issues)
        const status = error?.response?.status;
        if (status !== 401 && status !== 403) {
          toast({
            title: 'Automatické uložení selhalo',
            description: error?.response?.data?.error || error?.message || 'Koncept je uložen lokálně',
            status: 'warning',
            duration: 3000,
            isClosable: true,
          });
        }
      }
      
      setTimeout(() => setSaveStatus('idle'), 3000);
    } finally {
      isSavingRef.current = false;
    }
  }, [onSave, onError, toast, requiresId]);

  // Main auto-save effect
  useEffect(() => {
    if (!enabled) return;

    const dataString = JSON.stringify(data);
    
    // Skip if data hasn't changed
    if (dataString === lastDataRef.current) {
      return;
    }
    
    lastDataRef.current = dataString;

    // Save to localStorage immediately
    saveToLocalStorage(data);

    // Debounce backend save
    if (saveTimerRef.current) {
      clearTimeout(saveTimerRef.current);
    }

    saveTimerRef.current = setTimeout(() => {
      saveToBackend(data);
    }, debounceMs);

    return () => {
      if (saveTimerRef.current) {
        clearTimeout(saveTimerRef.current);
      }
    };
  }, [data, enabled, debounceMs, saveToLocalStorage, saveToBackend]);

  // Force immediate save
  const forceSave = useCallback(async () => {
    if (saveTimerRef.current) {
      clearTimeout(saveTimerRef.current);
    }
    saveToLocalStorage(data);
    await saveToBackend(data);
  }, [data, saveToLocalStorage, saveToBackend]);

  // Clear draft
  const clearDraft = useCallback(() => {
    try {
      localStorage.removeItem(storageKey);
      setHasDraft(false);
      setDraftAge(null);
      if (saveTimerRef.current) {
        clearTimeout(saveTimerRef.current);
      }
    } catch (err) {
      console.error('Failed to clear draft:', err);
    }
  }, [storageKey]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (saveTimerRef.current) {
        clearTimeout(saveTimerRef.current);
      }
    };
  }, []);

  return {
    saveStatus,
    lastSaved,
    forceSave,
    clearDraft,
    hasDraft,
    draftAge,
  };
}

/**
 * Load draft from localStorage
 */
export function loadDraft<T>(storageKey: string): T | null {
  try {
    const stored = localStorage.getItem(storageKey);
    if (!stored) return null;
    
    const parsed = JSON.parse(stored);
    return parsed.data || null;
  } catch (err) {
    console.error('Failed to load draft:', err);
    return null;
  }
}

/**
 * Get draft metadata
 */
export function getDraftMetadata(storageKey: string): { timestamp: number; age: number } | null {
  try {
    const stored = localStorage.getItem(storageKey);
    if (!stored) return null;
    
    const parsed = JSON.parse(stored);
    if (!parsed.timestamp) return null;
    
    const age = Math.floor((Date.now() - parsed.timestamp) / 60000); // minutes
    return {
      timestamp: parsed.timestamp,
      age,
    };
  } catch (err) {
    console.error('Failed to get draft metadata:', err);
    return null;
  }
}
