import { useState, useCallback, useRef } from 'react'
import { deepEqual } from '@/lib/utils'

export interface UndoRedoState<T> {
  past: T[]
  present: T
  future: T[]
}

interface UseUndoRedoReturn<T> {
  state: T
  setState: (newState: T | ((prev: T) => T)) => void
  undo: () => void
  redo: () => void
  canUndo: boolean
  canRedo: boolean
  clear: () => void
}

const MAX_HISTORY_SIZE = 50

export function useUndoRedo<T>(initialState: T): UseUndoRedoReturn<T> {
  const [history, setHistory] = useState<UndoRedoState<T>>({
    past: [],
    present: initialState,
    future: [],
  })
  
  // Track if we're in an undo/redo operation to prevent adding to history
  const isUndoRedoAction = useRef(false)

  const setState = useCallback((newState: T | ((prev: T) => T)) => {
    // Skip if this is an undo/redo action
    if (isUndoRedoAction.current) {
      isUndoRedoAction.current = false
      return
    }

    setHistory((currentHistory) => {
      const resolvedNewState =
        typeof newState === 'function'
          ? (newState as (prev: T) => T)(currentHistory.present)
          : newState

      // Don't add to history if state hasn't changed
      if (deepEqual(resolvedNewState, currentHistory.present)) {
        return currentHistory
      }

      const newPast = [...currentHistory.past, currentHistory.present]
      
      // Limit history size
      if (newPast.length > MAX_HISTORY_SIZE) {
        newPast.shift()
      }

      return {
        past: newPast,
        present: resolvedNewState,
        future: [], // Clear future on new action
      }
    })
  }, [])

  const undo = useCallback(() => {
    setHistory((currentHistory) => {
      if (currentHistory.past.length === 0) return currentHistory

      const previous = currentHistory.past[currentHistory.past.length - 1]
      const newPast = currentHistory.past.slice(0, currentHistory.past.length - 1)

      isUndoRedoAction.current = true

      return {
        past: newPast,
        present: previous,
        future: [currentHistory.present, ...currentHistory.future],
      }
    })
  }, [])

  const redo = useCallback(() => {
    setHistory((currentHistory) => {
      if (currentHistory.future.length === 0) return currentHistory

      const next = currentHistory.future[0]
      const newFuture = currentHistory.future.slice(1)

      isUndoRedoAction.current = true

      return {
        past: [...currentHistory.past, currentHistory.present],
        present: next,
        future: newFuture,
      }
    })
  }, [])

  const clear = useCallback(() => {
    setHistory({
      past: [],
      present: initialState,
      future: [],
    })
  }, [initialState])

  return {
    state: history.present,
    setState,
    undo,
    redo,
    canUndo: history.past.length > 0,
    canRedo: history.future.length > 0,
    clear,
  }
}
