"use client";

import { useState, useCallback, useRef } from "react";

// ========================================
// 레이아웃 히스토리 훅
// Undo/Redo 기능 제공
// ========================================

interface HistoryState<T> {
  past: T[];
  present: T;
  future: T[];
}

interface UseLayoutHistoryReturn<T> {
  // 현재 상태
  state: T;
  // 상태 설정 (히스토리에 기록)
  setState: (newState: T | ((prev: T) => T)) => void;
  // Undo
  undo: () => void;
  // Redo
  redo: () => void;
  // Undo 가능 여부
  canUndo: boolean;
  // Redo 가능 여부
  canRedo: boolean;
  // 히스토리 초기화 (새 레이아웃 로드 시)
  reset: (initialState: T) => void;
  // 히스토리 크기
  historySize: number;
}

/**
 * 레이아웃 히스토리 관리 훅
 * @param initialState 초기 상태
 * @param maxHistory 최대 히스토리 개수 (기본 50)
 */
export function useLayoutHistory<T>(
  initialState: T,
  maxHistory: number = 50
): UseLayoutHistoryReturn<T> {
  const [history, setHistory] = useState<HistoryState<T>>({
    past: [],
    present: initialState,
    future: [],
  });

  // 배치 업데이트를 위한 타이머
  const batchTimerRef = useRef<NodeJS.Timeout | null>(null);
  const pendingStateRef = useRef<T | null>(null);

  /**
   * 상태 설정 (히스토리에 기록)
   * 연속적인 드래그 등의 작업 시 배치 처리
   */
  const setState = useCallback(
    (newState: T | ((prev: T) => T)) => {
      setHistory((prev) => {
        const resolvedState =
          typeof newState === "function"
            ? (newState as (prev: T) => T)(prev.present)
            : newState;

        // 같은 상태면 무시
        if (JSON.stringify(resolvedState) === JSON.stringify(prev.present)) {
          console.log("[History] 상태 동일, 무시");
          return prev;
        }

        // 히스토리에 현재 상태 추가
        const newPast = [...prev.past, prev.present];
        
        // 최대 히스토리 개수 제한
        if (newPast.length > maxHistory) {
          newPast.shift();
        }

        console.log("[History] 상태 저장, past 크기:", newPast.length);

        return {
          past: newPast,
          present: resolvedState,
          future: [], // Redo 히스토리 초기화
        };
      });
    },
    [maxHistory]
  );

  /**
   * 배치 상태 설정 (드래그 중 연속 업데이트용)
   * 마지막 상태만 히스토리에 기록
   */
  const setStateBatched = useCallback(
    (newState: T | ((prev: T) => T), batchDelay: number = 300) => {
      // 현재 상태 업데이트 (히스토리에는 바로 기록하지 않음)
      setHistory((prev) => {
        const resolvedState =
          typeof newState === "function"
            ? (newState as (prev: T) => T)(prev.present)
            : newState;

        pendingStateRef.current = prev.present;

        return {
          ...prev,
          present: resolvedState,
        };
      });

      // 배치 타이머 리셋
      if (batchTimerRef.current) {
        clearTimeout(batchTimerRef.current);
      }

      // 일정 시간 후 히스토리에 기록
      batchTimerRef.current = setTimeout(() => {
        if (pendingStateRef.current !== null) {
          setHistory((prev) => {
            const newPast = [...prev.past, pendingStateRef.current as T];
            if (newPast.length > maxHistory) {
              newPast.shift();
            }
            pendingStateRef.current = null;
            return {
              ...prev,
              past: newPast,
              future: [],
            };
          });
        }
      }, batchDelay);
    },
    [maxHistory]
  );

  /**
   * Undo - 이전 상태로 복원
   */
  const undo = useCallback(() => {
    console.log("[History] Undo 호출");
    setHistory((prev) => {
      console.log("[History] Undo 실행, past 크기:", prev.past.length);
      if (prev.past.length === 0) {
        console.log("[History] Undo 불가 - past 비어있음");
        return prev;
      }

      const newPast = [...prev.past];
      const previousState = newPast.pop()!;

      console.log("[History] Undo 성공, 남은 past 크기:", newPast.length);

      return {
        past: newPast,
        present: previousState,
        future: [prev.present, ...prev.future],
      };
    });
  }, []);

  /**
   * Redo - 되돌린 상태 다시 적용
   */
  const redo = useCallback(() => {
    setHistory((prev) => {
      if (prev.future.length === 0) {
        return prev;
      }

      const newFuture = [...prev.future];
      const nextState = newFuture.shift()!;

      return {
        past: [...prev.past, prev.present],
        present: nextState,
        future: newFuture,
      };
    });
  }, []);

  /**
   * 히스토리 초기화 (새 레이아웃 로드 시)
   */
  const reset = useCallback((initialState: T) => {
    setHistory({
      past: [],
      present: initialState,
      future: [],
    });
  }, []);

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

export default useLayoutHistory;
