/**
 * 항적조회 전용 애니메이션 스토어
 *
 * - 재생/일시정지/정지
 * - 배속 조절 (1x ~ 1000x)
 * - 반복 재생
 * - requestAnimationFrame 기반 애니메이션
 */
import { create } from 'zustand';

// 애니메이션 프레임 관리용 변수 (스토어 외부)
let animationFrameId = null;
let lastFrameTime = null;

export const useTrackQueryAnimationStore = create((set, get) => {
  const animate = () => {
    const state = get();
    if (!state.isPlaying) return;

    const now = performance.now();
    if (lastFrameTime === null) {
      lastFrameTime = now;
    }

    const delta = now - lastFrameTime;
    lastFrameTime = now;

    const newTime = state.currentTime + delta * state.playbackSpeed;

    const effectiveEnd = state.loop ? state.loopEnd : state.endTime;
    const effectiveStart = state.loop ? state.loopStart : state.startTime;

    if (newTime >= effectiveEnd) {
      if (state.loop) {
        set({ currentTime: effectiveStart });
      } else {
        set({ currentTime: state.endTime, isPlaying: false });
        animationFrameId = null;
        lastFrameTime = null;
        return;
      }
    } else {
      set({ currentTime: newTime });
    }

    animationFrameId = requestAnimationFrame(animate);
  };

  return {
    isPlaying: false,
    currentTime: 0,
    startTime: 0,
    endTime: 0,
    playbackSpeed: 1,
    loop: false,
    loopStart: 0,
    loopEnd: 0,

    play: () => {
      const state = get();
      if (state.endTime <= state.startTime) return;

      lastFrameTime = null;

      if (state.loop) {
        if (state.currentTime < state.loopStart || state.currentTime >= state.loopEnd) {
          set({ isPlaying: true, currentTime: state.loopStart });
        } else {
          set({ isPlaying: true });
        }
      } else {
        set({ isPlaying: true });
      }

      animationFrameId = requestAnimationFrame(animate);
    },

    pause: () => {
      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId);
        animationFrameId = null;
      }
      lastFrameTime = null;
      set({ isPlaying: false });
    },

    stop: () => {
      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId);
        animationFrameId = null;
      }
      lastFrameTime = null;
      set({ isPlaying: false, currentTime: get().startTime });
    },

    setCurrentTime: (time) => {
      const { startTime, endTime } = get();
      const clampedTime = Math.max(startTime, Math.min(endTime, time));
      set({ currentTime: clampedTime });
    },

    setPlaybackSpeed: (speed) => set({ playbackSpeed: speed }),

    toggleLoop: () => set({ loop: !get().loop }),

    setLoopSection: (start, end) => {
      const { startTime, endTime } = get();
      const clampedStart = Math.max(startTime, Math.min(end, start));
      const clampedEnd = Math.max(start, Math.min(endTime, end));
      set({ loopStart: clampedStart, loopEnd: clampedEnd });
    },

    resetLoopSection: () => {
      const { startTime, endTime } = get();
      set({ loopStart: startTime, loopEnd: endTime });
    },

    setTimeRange: (start, end) => {
      set({
        startTime: start,
        endTime: end,
        currentTime: start,
        loopStart: start,
        loopEnd: end,
      });
    },

    getProgress: () => {
      const { currentTime, startTime, endTime } = get();
      if (endTime <= startTime) return 0;
      return ((currentTime - startTime) / (endTime - startTime)) * 100;
    },

    getLoopProgress: () => {
      const { startTime, endTime, loopStart, loopEnd } = get();
      if (endTime <= startTime) return { start: 0, end: 100 };
      const totalDuration = endTime - startTime;
      return {
        start: ((loopStart - startTime) / totalDuration) * 100,
        end: ((loopEnd - startTime) / totalDuration) * 100,
      };
    },

    reset: () => {
      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId);
        animationFrameId = null;
      }
      lastFrameTime = null;
      set({
        isPlaying: false,
        currentTime: 0,
        startTime: 0,
        endTime: 0,
        playbackSpeed: 1,
        loop: false,
        loopStart: 0,
        loopEnd: 0,
      });
    },
  };
});

/** 재생 가능한 배속 옵션 */
export const PLAYBACK_SPEED_OPTIONS = [1, 5, 10, 50, 100, 1000];
