import { useState, useEffect, useCallback, useRef } from 'react';
import { useNavigationStore } from '../store/navigation';

export interface UseFormStateOptions<T> {
  formId: string;
  defaultValues: T;
  autoSave?: boolean;
  saveDelay?: number;
  onRestore?: (data: T) => void;
  onSave?: (data: T) => void;
  validate?: (data: T) => Record<string, string> | null;
}

export interface FormStateReturn<T> {
  formData: T;
  updateFormData: (updates: Partial<T>) => void;
  setFormData: (data: T) => void;
  resetForm: () => void;
  submitForm: () => Promise<void>;
  hasChanges: boolean;
  isRestored: boolean;
  isSaving: boolean;
  errors: Record<string, string>;
  isValid: boolean;
}

export const useFormState = <T extends Record<string, any>>({
  formId,
  defaultValues,
  autoSave = true,
  saveDelay = 1000,
  onRestore,
  onSave,
  validate,
}: UseFormStateOptions<T>): FormStateReturn<T> => {
  const { saveFormState, restoreFormState, clearFormState } = useNavigationStore();
  const [formData, setFormDataState] = useState<T>(defaultValues);
  const [hasChanges, setHasChanges] = useState(false);
  const [isRestored, setIsRestored] = useState(false);
  const [isSaving, setIsSaving] = useState(false);
  const [errors, setErrors] = useState<Record<string, string>>({});

  const initialDataRef = useRef<T>(defaultValues);
  const formDataRef = useRef<T>(formData);
  const saveTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Update ref when formData changes
  useEffect(() => {
    formDataRef.current = formData;
  }, [formData]);

  // Validation
  const validateForm = useCallback((data: T) => {
    if (!validate) return {};

    const validationErrors = validate(data);
    return validationErrors || {};
  }, [validate]);

  // Restore form state on mount
  useEffect(() => {
    const restoredState = restoreFormState(formId);
    if (restoredState && !isRestored) {
      const restoredData = { ...defaultValues, ...restoredState.data };
      setFormDataState(restoredData);
      setHasChanges(restoredState.isDirty);
      setIsRestored(true);

      if (onRestore) {
        onRestore(restoredData);
      }
    }
  }, [formId, restoreFormState, defaultValues, isRestored, onRestore]);

  // Auto-save with debounce
  useEffect(() => {
    if (!autoSave || !hasChanges) return;

    // Clear existing timeout
    if (saveTimeoutRef.current) {
      clearTimeout(saveTimeoutRef.current);
    }

    // Set new timeout
    saveTimeoutRef.current = setTimeout(async () => {
      try {
        setIsSaving(true);
        saveFormState(formId, formDataRef.current, hasChanges);

        if (onSave) {
          await onSave(formDataRef.current);
        }
      } catch (error) {
        console.warn('Form auto-save failed:', error);
      } finally {
        setIsSaving(false);
      }
    }, saveDelay);

    // Cleanup timeout
    return () => {
      if (saveTimeoutRef.current) {
        clearTimeout(saveTimeoutRef.current);
      }
    };
  }, [formData, hasChanges, autoSave, saveDelay, formId, saveFormState, onSave]);

  // Validate when form data changes
  useEffect(() => {
    if (hasChanges) {
      const validationErrors = validateForm(formData);
      setErrors(validationErrors);
    }
  }, [formData, hasChanges, validateForm]);

  const updateFormData = useCallback((updates: Partial<T>) => {
    setFormDataState((current) => {
      const updated = { ...current, ...updates };
      const hasActualChanges = JSON.stringify(updated) !== JSON.stringify(initialDataRef.current);
      setHasChanges(hasActualChanges);
      return updated;
    });
  }, []);

  const setFormData = useCallback((data: T) => {
    setFormDataState(data);
    const hasActualChanges = JSON.stringify(data) !== JSON.stringify(initialDataRef.current);
    setHasChanges(hasActualChanges);
  }, []);

  const resetForm = useCallback(() => {
    setFormDataState(defaultValues);
    setHasChanges(false);
    setErrors({});
    clearFormState(formId);
    initialDataRef.current = { ...defaultValues };
  }, [defaultValues, formId, clearFormState]);

  const submitForm = useCallback(async () => {
    const validationErrors = validateForm(formDataRef.current);
    setErrors(validationErrors);

    if (Object.keys(validationErrors).length > 0) {
      throw new Error('Form validation failed');
    }

    try {
      setHasChanges(false);
      clearFormState(formId);
      initialDataRef.current = { ...formDataRef.current };

      if (onSave) {
        await onSave(formDataRef.current);
      }
    } catch (error) {
      setHasChanges(true); // Restore changes state on error
      throw error;
    }
  }, [validateForm, formId, clearFormState, onSave]);

  const isValid = Object.keys(errors).length === 0;

  return {
    formData,
    updateFormData,
    setFormData,
    resetForm,
    submitForm,
    hasChanges,
    isRestored,
    isSaving,
    errors,
    isValid,
  };
};