import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import type { HistoryFrame } from '../components/korea/fleetClusterTypes';
import type { GearCorrelationItem, CorrelationVesselTrack } from '../services/vesselAnalysis';
import {
  buildMemberTripsData,
  buildCorrelationTripsData,
  buildCenterTrailData,
  buildSnapshotRanges,
} from './gearReplayPreprocess';

// ── Pre-processed data types for deck.gl layers ──────────────────

export interface TripsLayerDatum {
  id: string;
  path: [number, number][];
  timestamps: number[];
  color: [number, number, number, number];
}

export interface MemberPosition {
  mmsi: string;
  name: string;
  lon: number;
  lat: number;
  cog: number;
  role: string;
  isParent: boolean;
  isGear: boolean;
  stale: boolean;
}

export interface CenterTrailSegment {
  path: [number, number][];
  isInterpolated: boolean;
}

// ── Speed factor: 1x = 30 real seconds covers 12 timeline hours ──
const SPEED_FACTOR = (12 * 60 * 60 * 1000) / (30 * 1000); // 1440

// ── Module-level rAF state (outside React) ───────────────────────
let animationFrameId: number | null = null;
let lastFrameTime: number | null = null;

// ── Store interface ───────────────────────────────────────────────

interface GearReplayState {
  // Playback state
  isPlaying: boolean;
  currentTime: number;
  startTime: number;
  endTime: number;
  playbackSpeed: number;

  // Source data
  historyFrames: HistoryFrame[];
  frameTimes: number[];
  selectedGroupKey: string | null;

  // Pre-computed layer data
  memberTripsData: TripsLayerDatum[];
  correlationTripsData: TripsLayerDatum[];
  centerTrailSegments: CenterTrailSegment[];
  centerDotsPositions: [number, number][];
  snapshotRanges: number[];

  // Filter / display state
  enabledModels: Set<string>;
  enabledVessels: Set<string>;
  hoveredMmsi: string | null;
  correlationByModel: Map<string, GearCorrelationItem[]>;
  showTrails: boolean;
  showLabels: boolean;

  // Actions
  loadHistory: (
    frames: HistoryFrame[],
    corrTracks: CorrelationVesselTrack[],
    corrData: GearCorrelationItem[],
    enabledModels: Set<string>,
    enabledVessels: Set<string>,
  ) => void;
  play: () => void;
  pause: () => void;
  seek: (timeMs: number) => void;
  setPlaybackSpeed: (speed: number) => void;
  setEnabledModels: (models: Set<string>) => void;
  setEnabledVessels: (vessels: Set<string>) => void;
  setHoveredMmsi: (mmsi: string | null) => void;
  setShowTrails: (show: boolean) => void;
  setShowLabels: (show: boolean) => void;
  updateCorrelation: (corrData: GearCorrelationItem[], corrTracks: CorrelationVesselTrack[]) => void;
  reset: () => void;
}

// ── Store ─────────────────────────────────────────────────────────

export const useGearReplayStore = create<GearReplayState>()(
  subscribeWithSelector((set, get) => {
    const animate = (): void => {
      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 * SPEED_FACTOR * state.playbackSpeed;

      if (newTime >= state.endTime) {
        set({ currentTime: state.startTime });
        animationFrameId = requestAnimationFrame(animate);
        return;
      }

      set({ currentTime: newTime });
      animationFrameId = requestAnimationFrame(animate);
    };

    return {
      // Playback state
      isPlaying: false,
      currentTime: 0,
      startTime: 0,
      endTime: 0,
      playbackSpeed: 1,

      // Source data
      historyFrames: [],
      frameTimes: [],
      selectedGroupKey: null,

      // Pre-computed layer data
      memberTripsData: [],
      correlationTripsData: [],
      centerTrailSegments: [],
      centerDotsPositions: [],
      snapshotRanges: [],

      // Filter / display state
      enabledModels: new Set<string>(),
      enabledVessels: new Set<string>(),
      hoveredMmsi: null,
      showTrails: true,
      showLabels: true,
      correlationByModel: new Map<string, GearCorrelationItem[]>(),

      // ── Actions ────────────────────────────────────────────────

      loadHistory: (frames, corrTracks, corrData, enabledModels, enabledVessels) => {
        const startTime = Date.now() - 12 * 60 * 60 * 1000;
        const endTime = Date.now();
        const frameTimes = frames.map(f => new Date(f.snapshotTime).getTime());

        const memberTrips = buildMemberTripsData(frames, startTime);
        const corrTrips = buildCorrelationTripsData(corrTracks, startTime);
        const { segments, dots } = buildCenterTrailData(frames);
        const ranges = buildSnapshotRanges(frames, startTime, endTime);

        const byModel = new Map<string, GearCorrelationItem[]>();
        for (const c of corrData) {
          const list = byModel.get(c.modelName) ?? [];
          list.push(c);
          byModel.set(c.modelName, list);
        }

        set({
          historyFrames: frames,
          frameTimes,
          startTime,
          endTime,
          currentTime: startTime,
          memberTripsData: memberTrips,
          correlationTripsData: corrTrips,
          centerTrailSegments: segments,
          centerDotsPositions: dots,
          snapshotRanges: ranges,
          enabledModels,
          enabledVessels,
          correlationByModel: byModel,
          selectedGroupKey: frames[0]?.groupKey ?? null,
        });
      },

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

        lastFrameTime = null;

        if (state.currentTime >= state.endTime) {
          set({ isPlaying: true, currentTime: state.startTime });
        } else {
          set({ isPlaying: true });
        }

        animationFrameId = requestAnimationFrame(animate);
      },

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

      seek: (timeMs) => {
        const { startTime, endTime } = get();
        set({ currentTime: Math.max(startTime, Math.min(endTime, timeMs)) });
      },

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

      setEnabledModels: (models) => set({ enabledModels: models }),

      setEnabledVessels: (vessels) => set({ enabledVessels: vessels }),

      setHoveredMmsi: (mmsi) => set({ hoveredMmsi: mmsi }),
      setShowTrails: (show) => set({ showTrails: show }),
      setShowLabels: (show) => set({ showLabels: show }),

      updateCorrelation: (corrData, corrTracks) => {
        const state = get();
        if (state.historyFrames.length === 0) {
          console.log('[GearReplayStore] updateCorrelation 스킵: historyFrames 비어있음');
          return;
        }
        const byModel = new Map<string, GearCorrelationItem[]>();
        for (const c of corrData) {
          const list = byModel.get(c.modelName) ?? [];
          list.push(c);
          byModel.set(c.modelName, list);
        }
        const corrTrips = buildCorrelationTripsData(corrTracks, state.startTime);
        console.log('[GearReplayStore] updateCorrelation:', {
          corrData: corrData.length,
          models: [...byModel.keys()],
          corrTrips: corrTrips.length,
          corrTracks: corrTracks.length,
        });
        set({ correlationByModel: byModel, correlationTripsData: corrTrips });
      },

      reset: () => {
        if (animationFrameId !== null) {
          cancelAnimationFrame(animationFrameId);
          animationFrameId = null;
        }
        lastFrameTime = null;
        set({
          isPlaying: false,
          currentTime: 0,
          startTime: 0,
          endTime: 0,
          playbackSpeed: 1,
          historyFrames: [],
          frameTimes: [],
          selectedGroupKey: null,
          memberTripsData: [],
          correlationTripsData: [],
          centerTrailSegments: [],
          centerDotsPositions: [],
          snapshotRanges: [],
          enabledModels: new Set<string>(),
          enabledVessels: new Set<string>(),
          hoveredMmsi: null,
          showTrails: true,
          showLabels: true,
          correlationByModel: new Map<string, GearCorrelationItem[]>(),
        });
      },
    };
  }),
);
