/**
 * Provider that wraps the builder and adds undo/redo functionality
 * Automatically stores state snapshots when significant changes occur
 */

"use client";

import { createContext, useContext, useEffect, useRef, type ReactNode } from 'react';
import { useBuilderState, useBuilderDispatch } from '@/lib/admin/builder/context';
import { useSimpleUndoRedo } from '@/lib/admin/builder/useSimpleUndoRedo';
import type { BuilderState } from '@/lib/admin/builder/context';

interface UndoRedoContextValue {
  canUndo: boolean;
  canRedo: boolean;
  undo: () => void;
  redo: () => void;
  store: () => void;
  clear: () => void;
  resetDirty: () => void; // Сброс isDirty флага
}

const UndoRedoContext = createContext<UndoRedoContextValue | undefined>(undefined);

interface BuilderUndoRedoProviderProps {
  children: ReactNode;
}

export function BuilderUndoRedoProvider({ children }: BuilderUndoRedoProviderProps) {
  const state = useBuilderState();
  const dispatch = useBuilderDispatch();
  const previousStateRef = useRef<BuilderState>(state);
  const isRestoringRef = useRef(false);

  // Функция для сброса isDirty
  const resetDirty = () => {
    dispatch({ type: 'reset', payload: { ...state, isDirty: false } });
  };

  const undoRedo = useSimpleUndoRedo(
    state,
    (newState) => {
      isRestoringRef.current = true;
      dispatch({ type: 'reset', payload: newState });
    }
  );

  // Auto-store state when significant changes occur
  useEffect(() => {
    // Don't store if we're in the middle of restoring from undo/redo
    if (isRestoringRef.current) {
      isRestoringRef.current = false;
      previousStateRef.current = state;
      return;
    }

    const prev = previousStateRef.current;
    
    // Check for significant changes that should trigger a store
    const shouldStore = (
      // Screen count changed
      prev.screens.length !== state.screens.length ||
      
      // Selected screen changed
      prev.selectedScreenId !== state.selectedScreenId ||
      
      // Meta data changed  
      JSON.stringify(prev.meta) !== JSON.stringify(state.meta) ||
      
      // Screen structure changed (templates, navigation, etc.)
      prev.screens.some((prevScreen, index) => {
        const currentScreen = state.screens[index];
        if (!currentScreen || prevScreen.id !== currentScreen.id) return true;
        
        return (
          prevScreen.template !== currentScreen.template ||
          JSON.stringify(prevScreen.navigation) !== JSON.stringify(currentScreen.navigation) ||
          JSON.stringify(prevScreen.title) !== JSON.stringify(currentScreen.title)
        );
      })
    );

    if (shouldStore) {
      // Store the previous state (not current) so we can undo to it
      undoRedo.store();
      previousStateRef.current = state;
    }
  }, [state, undoRedo]);

  // Store initial state
  useEffect(() => {
    undoRedo.store();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const contextValue: UndoRedoContextValue = {
    canUndo: undoRedo.canUndo,
    canRedo: undoRedo.canRedo,
    undo: undoRedo.undo,
    redo: undoRedo.redo,
    store: undoRedo.store,
    clear: undoRedo.clear,
    resetDirty,
  };

  return (
    <UndoRedoContext.Provider value={contextValue}>
      {children}
    </UndoRedoContext.Provider>
  );
}

export function useBuilderUndoRedo(): UndoRedoContextValue {
  const context = useContext(UndoRedoContext);
  if (!context) {
    throw new Error('useBuilderUndoRedo must be used within BuilderUndoRedoProvider');
  }
  return context;
}
