/**
 * 선박 항적 애니메이션 상태 관리 스토어
 * 참조: mda-react-front/src/tracking/stores/animationStore.ts
 *
 * 시간 기반 애니메이션을 제어하고 현재 시간의 선박 위치를 계산
 */

import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import useMergedTrackStore from './mergedTrackStore';
import useReplayStore from './replayStore';

/**
 * 재생 상태 (레거시 호환)
 */
export const PlaybackState = {
  IDLE: 'IDLE',
  PLAYING: 'PLAYING',
  PAUSED: 'PAUSED',
  STOPPED: 'STOPPED',
};

/**
 * 두 지점 간의 방향(heading) 계산
 */
function calculateHeading(p1, p2) {
  const [lon1, lat1] = p1;
  const [lon2, lat2] = p2;
  const dx = lon2 - lon1;
  const dy = lat2 - lat1;
  let angle = (Math.atan2(dx, dy) * 180) / Math.PI;
  if (angle < 0) angle += 360;
  return angle;
}

/**
 * 두 지점 사이의 위치를 시간 기반으로 보간
 */
function interpolatePosition(p1, p2, t1, t2, currentTime) {
  if (t1 === t2) return p1;
  const ratio = (currentTime - t1) / (t2 - t1);
  return [
    p1[0] + (p2[0] - p1[0]) * ratio,
    p1[1] + (p2[1] - p1[1]) * ratio,
  ];
}

/**
 * 청크 기반 데이터에서 시간 범위 추출
 */
function getTimeRangeFromVessels() {
  const vesselChunks = useMergedTrackStore.getState().vesselChunks;

  if (vesselChunks.size === 0) {
    return null;
  }

  let minTime = Infinity;
  let maxTime = -Infinity;

  vesselChunks.forEach((vessel) => {
    const mergedPath = useMergedTrackStore.getState().getMergedPath(vessel.vesselId);
    if (mergedPath && mergedPath.timestampsMs.length > 0) {
      minTime = Math.min(minTime, mergedPath.timestampsMs[0]);
      maxTime = Math.max(maxTime, mergedPath.timestampsMs[mergedPath.timestampsMs.length - 1]);
    }
  });

  if (minTime === Infinity || maxTime === -Infinity) {
    return null;
  }

  return { start: minTime, end: maxTime };
}

/**
 * 애니메이션 스토어
 */
const useAnimationStore = create(subscribeWithSelector((set, get) => ({
  // ========== 재생 상태 ==========
  isPlaying: false,
  playbackState: PlaybackState.IDLE, // 레거시 호환
  currentTime: 0,
  startTime: 0,
  endTime: 0,
  playbackSpeed: 1,
  loop: false,
  loopEnabled: false, // 레거시 호환

  // ========== 내부 상태 ==========
  animationFrameId: null,
  lastFrameTime: 0,

  /**
   * 재생 시작
   */
  play: () => {
    const state = get();
    if (state.isPlaying) return;

    const vesselChunks = useMergedTrackStore.getState().vesselChunks;
    if (vesselChunks.size === 0) return;

    const timeRange = getTimeRangeFromVessels();
    if (!timeRange) return;

    // 시간 범위 설정
    if (
      state.startTime === 0 ||
      state.endTime === 0 ||
      state.currentTime < timeRange.start ||
      state.currentTime > timeRange.end
    ) {
      set({
        startTime: timeRange.start,
        endTime: timeRange.end,
        currentTime: timeRange.start,
      });
    }

    // 끝에 도달했으면 처음부터
    if (state.currentTime >= state.endTime) {
      set({ currentTime: state.startTime });
    }

    set({
      isPlaying: true,
      playbackState: PlaybackState.PLAYING,
      lastFrameTime: performance.now(),
    });

    // 애니메이션 루프 시작
    const animate = (timestamp) => {
      const state = get();
      if (!state.isPlaying) return;

      const deltaTime = timestamp - state.lastFrameTime;
      const timeIncrement = (deltaTime / 1000) * state.playbackSpeed;
      let newTime = state.currentTime + timeIncrement * 1000;

      if (newTime > state.endTime) {
        if (state.loop || state.loopEnabled) {
          newTime = state.startTime;
        } else {
          newTime = state.endTime;
          set({
            isPlaying: false,
            playbackState: PlaybackState.STOPPED,
          });
        }
      }

      set({
        currentTime: newTime,
        lastFrameTime: timestamp,
      });

      if (get().isPlaying) {
        const frameId = requestAnimationFrame(animate);
        set({ animationFrameId: frameId });
      }
    };

    const frameId = requestAnimationFrame(animate);
    set({ animationFrameId: frameId });
  },

  /**
   * 일시정지
   */
  pause: () => {
    const { animationFrameId } = get();
    if (animationFrameId !== null) {
      cancelAnimationFrame(animationFrameId);
    }
    set({
      isPlaying: false,
      playbackState: PlaybackState.PAUSED,
      animationFrameId: null,
    });
  },

  /**
   * 정지 (처음으로)
   */
  stop: () => {
    const { animationFrameId } = get();
    if (animationFrameId !== null) {
      cancelAnimationFrame(animationFrameId);
    }

    const timeRange = getTimeRangeFromVessels();
    const startTime = timeRange?.start || 0;

    set({
      isPlaying: false,
      playbackState: PlaybackState.STOPPED,
      currentTime: startTime,
      animationFrameId: null,
    });
  },

  /**
   * 특정 시간으로 이동
   */
  seekTo: (time) => {
    const state = get();
    const clampedTime = Math.max(state.startTime, Math.min(time, state.endTime));
    set({ currentTime: clampedTime });
  },

  /**
   * 현재 시간 설정 (레거시 호환)
   */
  setCurrentTime: (time) => {
    set({ currentTime: time });
  },

  /**
   * 재생 속도 설정
   */
  setPlaybackSpeed: (speed) => {
    set({ playbackSpeed: speed });
  },

  /**
   * 반복 재생 토글
   */
  toggleLoop: () => {
    set((state) => ({
      loop: !state.loop,
      loopEnabled: !state.loopEnabled,
    }));
  },

  /**
   * 시간 범위 업데이트
   */
  updateTimeRange: () => {
    const timeRange = getTimeRangeFromVessels();
    if (timeRange) {
      const state = get();
      const newCurrentTime =
        state.currentTime === 0 ||
        state.currentTime < timeRange.start ||
        state.currentTime > timeRange.end
          ? timeRange.start
          : state.currentTime;

      set({
        startTime: timeRange.start,
        endTime: timeRange.end,
        currentTime: newCurrentTime,
      });
      return timeRange;
    }
    return { start: 0, end: 0 };
  },

  /**
   * 시간 범위 직접 설정
   */
  setTimeRange: (startTime, endTime) => {
    set({
      startTime,
      endTime,
      currentTime: startTime,
    });
  },

  /**
   * 진행률 계산 (0 ~ 100)
   */
  getProgress: () => {
    const { currentTime, startTime, endTime } = get();
    if (endTime === startTime) return 0;
    return ((currentTime - startTime) / (endTime - startTime)) * 100;
  },

  /**
   * 현재 시간의 선박 위치 계산 (핵심 메서드)
   * 참조: mda-react-front/src/tracking/stores/animationStore.ts - getCurrentVesselPositions
   */
  getCurrentVesselPositions: () => {
    const { currentTime } = get();
    const vesselChunks = useMergedTrackStore.getState().vesselChunks;
    const positions = [];

    vesselChunks.forEach((vessel, vesselId) => {
      if (!vessel) return;

      const mergedPath = useMergedTrackStore.getState().getMergedPath(vesselId);
      if (!mergedPath || mergedPath.timestampsMs.length === 0) return;

      const timestampsMs = mergedPath.timestampsMs;
      const firstTime = timestampsMs[0];
      const lastTime = timestampsMs[timestampsMs.length - 1];

      // 시간 범위 체크
      if (currentTime < firstTime || currentTime > lastTime) {
        return;
      }

      // 이진 탐색으로 현재 시간에 해당하는 인덱스 찾기
      let left = 0;
      let right = timestampsMs.length - 1;

      while (left < right) {
        const mid = Math.floor((left + right) / 2);
        if (timestampsMs[mid] < currentTime) {
          left = mid + 1;
        } else {
          right = mid;
        }
      }

      const idx1 = Math.max(0, left - 1);
      const idx2 = Math.min(timestampsMs.length - 1, left);

      let finalPosition;
      let heading;
      let speed;

      if (idx1 === idx2 || timestampsMs[idx1] === timestampsMs[idx2]) {
        finalPosition = mergedPath.geometry[idx1];
        heading = 0;
        speed = mergedPath.speeds[idx1] || 0;
      } else {
        finalPosition = interpolatePosition(
          mergedPath.geometry[idx1],
          mergedPath.geometry[idx2],
          timestampsMs[idx1],
          timestampsMs[idx2],
          currentTime
        );
        heading = calculateHeading(mergedPath.geometry[idx1], mergedPath.geometry[idx2]);
        const speedRatio = (currentTime - timestampsMs[idx1]) / (timestampsMs[idx2] - timestampsMs[idx1]);
        speed = (mergedPath.speeds[idx1] || 0) + ((mergedPath.speeds[idx2] || 0) - (mergedPath.speeds[idx1] || 0)) * speedRatio;
      }

      positions.push({
        vesselId,
        position: finalPosition,
        heading,
        speed,
        timestamp: currentTime,
        // 추가 정보
        shipKindCode: vessel.shipKindCode || '000027',
        shipName: vessel.shipName || '',
        sigSrcCd: vessel.sigSrcCd,
      });
    });

    return positions;
  },

  /**
   * 초기화
   */
  reset: () => {
    const { animationFrameId } = get();
    if (animationFrameId !== null) {
      cancelAnimationFrame(animationFrameId);
    }

    set({
      isPlaying: false,
      playbackState: PlaybackState.IDLE,
      currentTime: 0,
      playbackSpeed: 1,
      startTime: 0,
      endTime: 0,
      animationFrameId: null,
      lastFrameTime: 0,
      loop: false,
      loopEnabled: false,
    });
  },
})));

export default useAnimationStore;
