import axios from 'axios';

import { useCallback, useEffect, useRef, useState } from 'react';

interface UseAutoSaveOptions {
  content: string;
  siteId: number;
  draftId: number;
  enabled?: boolean;
  intervalMs?: number;
}

interface UseAutoSaveReturn {
  isSaving: boolean;
  hasUnsavedChanges: boolean;
  lastSavedAt: Date | null;
  error: string | null;
  saveNow: () => Promise<void>;
}

export function useAutoSave({
  content,
  siteId,
  draftId,
  enabled = true,
  intervalMs = 30000, // 30 seconds default
}: UseAutoSaveOptions): UseAutoSaveReturn {
  const [isSaving, setIsSaving] = useState(false);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  const [lastSavedAt, setLastSavedAt] = useState<Date | null>(null);
  const [error, setError] = useState<string | null>(null);
  const abortControllerRef = useRef<AbortController | null>(null);
  const intervalTimerRef = useRef<NodeJS.Timeout | null>(null);
  const lastSavedContentRef = useRef<string>(content);
  const contentRef = useRef<string>(content);
  const isSavingRef = useRef<boolean>(false);
  const hasUnsavedChangesRef = useRef<boolean>(false);

  // Keep refs in sync with state
  useEffect(() => {
    contentRef.current = content;
  }, [content]);

  useEffect(() => {
    isSavingRef.current = isSaving;
  }, [isSaving]);

  useEffect(() => {
    hasUnsavedChangesRef.current = hasUnsavedChanges;
  }, [hasUnsavedChanges]);

  const saveContent = useCallback(async () => {
    // Don't save if disabled, already saving, or no changes
    if (!enabled || isSavingRef.current || !hasUnsavedChangesRef.current) {
      return;
    }

    // Abort any pending request
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }

    const abortController = new AbortController();
    abortControllerRef.current = abortController;

    setIsSaving(true);
    setError(null);

    try {
      await axios.patch(
        route('content-editor.update', { site: siteId, aiDraft: draftId }),
        {
          content: contentRef.current,
        },
        {
          signal: abortController.signal,
        },
      );

      if (!abortController.signal.aborted) {
        setIsSaving(false);
        setHasUnsavedChanges(false);
        setLastSavedAt(new Date());
        setError(null);
        lastSavedContentRef.current = contentRef.current;
      }
    } catch (err) {
      if (!abortController.signal.aborted) {
        setIsSaving(false);
        if (axios.isAxiosError(err) && err.response) {
          setError(err.response.data.message || 'Failed to save content');
        } else {
          setError('Failed to save content');
        }
      }
    }
  }, [enabled, siteId, draftId]);

  // Track unsaved changes
  useEffect(() => {
    if (content !== lastSavedContentRef.current) {
      setHasUnsavedChanges(true);
    }
  }, [content]);

  // Auto-save interval
  useEffect(() => {
    // Clear any existing interval
    if (intervalTimerRef.current) {
      clearInterval(intervalTimerRef.current);
    }

    // Don't start interval if disabled
    if (!enabled) {
      return;
    }

    // Set up auto-save interval
    intervalTimerRef.current = setInterval(() => {
      saveContent();
    }, intervalMs);

    // Cleanup function
    return () => {
      if (intervalTimerRef.current) {
        clearInterval(intervalTimerRef.current);
      }
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }
    };
  }, [enabled, intervalMs, saveContent]);

  return {
    isSaving,
    hasUnsavedChanges,
    lastSavedAt,
    error,
    saveNow: saveContent,
  };
}
