/**
 * Store Zustand pour gérer l'état du player
 * FE-TYPE-011: Fully typed store
 */

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { Track, PlayerState, PlayerControls } from '../types';

// FE-TYPE-011: Fully typed store interface
export interface PlayerStore extends PlayerState, PlayerControls {
  setCurrentTime: (time: number) => void;
  setDuration: (duration: number) => void;
  removeFromQueue: (index: number) => void;
  reorderQueue: (from: number, to: number) => void;
}

export const usePlayerStore = create<PlayerStore>()(
  persist(
    (set, get) => ({
      // État initial
      currentTrack: null,
      isPlaying: false,
      currentTime: 0,
      duration: 0,
      volume: 100,
      muted: false,
      queue: [],
      currentIndex: -1,
      repeat: 'off',
      shuffle: false,

      // Actions de contrôle
      play: (track?: Track) => {
        if (!track) {
          // Si pas de track fourni, reprendre la lecture
          set({ isPlaying: true });
          return;
        }

        const { queue } = get();
        const trackIndex = queue.findIndex((t) => t.id === track.id);

        if (trackIndex >= 0) {
          // Track déjà dans la queue
          set({
            currentTrack: track,
            currentIndex: trackIndex,
            isPlaying: true,
            currentTime: 0,
          });
        } else {
          // Nouvelle track, l'ajouter à la queue
          const newQueue = [...queue, track];
          set({
            currentTrack: track,
            currentIndex: newQueue.length - 1,
            queue: newQueue,
            isPlaying: true,
            currentTime: 0,
          });
        }
      },

      pause: () => {
        set({ isPlaying: false });
      },

      resume: () => {
        set({ isPlaying: true });
      },

      stop: () => {
        set({ isPlaying: false, currentTime: 0 });
      },

      next: () => {
        const { queue, currentIndex, repeat, shuffle } = get();

        if (queue.length === 0) return;

        let nextIndex = currentIndex;

        if (shuffle) {
          // Mode shuffle: choisir une track aléatoire
          nextIndex = Math.floor(Math.random() * queue.length);
        } else if (currentIndex < queue.length - 1) {
          // Track suivante dans la queue
          nextIndex = currentIndex + 1;
        } else if (repeat === 'playlist') {
          // Répéter la playlist: revenir au début
          nextIndex = 0;
        } else {
          // Pas de track suivante
          return;
        }

        if (nextIndex !== currentIndex && nextIndex < queue.length) {
          set({
            currentIndex: nextIndex,
            currentTrack: queue[nextIndex],
            currentTime: 0,
            isPlaying: true,
          });
        }
      },

      previous: () => {
        const { queue, currentIndex } = get();

        if (queue.length === 0 || currentIndex <= 0) return;

        const prevIndex = currentIndex - 1;
        set({
          currentIndex: prevIndex,
          currentTrack: queue[prevIndex],
          currentTime: 0,
          isPlaying: true,
        });
      },

      seek: (time: number) => {
        const { duration } = get();
        const clampedTime = Math.max(0, Math.min(time, duration || 0));
        set({ currentTime: clampedTime });
      },

      setCurrentTime: (time: number) => {
        const { duration } = get();
        const clampedTime = Math.max(0, Math.min(time, duration || 0));
        set({ currentTime: clampedTime });
      },

      setDuration: (duration: number) => {
        set({ duration: Math.max(0, duration) });
      },

      setVolume: (volume: number) => {
        const clampedVolume = Math.max(0, Math.min(100, volume));
        set({ volume: clampedVolume });
      },

      toggleMute: () => {
        set({ muted: !get().muted });
      },

      toggleShuffle: () => {
        set({ shuffle: !get().shuffle });
      },

      setRepeat: (mode: 'off' | 'track' | 'playlist') => {
        set({ repeat: mode });
      },

      // Queue management
      addToQueue: (tracks: Track[]) => {
        const { queue } = get();
        const newQueue = [...queue, ...tracks];
        set({ queue: newQueue });
      },

      removeFromQueue: (index: number) => {
        const { queue, currentIndex } = get();
        if (index < 0 || index >= queue.length) return;

        const newQueue = queue.filter((_, i) => i !== index);

        // Ajuster l'index courant si nécessaire
        let newIndex = currentIndex;
        if (index < currentIndex) {
          newIndex = currentIndex - 1;
        } else if (index === currentIndex) {
          // Si on supprime la track courante, passer à la suivante ou arrêter
          if (newQueue.length > 0) {
            newIndex = Math.min(newIndex, newQueue.length - 1);
            set({
              queue: newQueue,
              currentIndex: newIndex,
              currentTrack: newQueue[newIndex] || null,
              isPlaying: newQueue[newIndex] ? get().isPlaying : false,
            });
            return;
          } else {
            newIndex = -1;
            set({
              queue: newQueue,
              currentIndex: newIndex,
              currentTrack: null,
              isPlaying: false,
            });
            return;
          }
        }

        set({ queue: newQueue, currentIndex: newIndex });
      },

      reorderQueue: (from: number, to: number) => {
        const { queue, currentIndex } = get();
        if (
          from < 0 ||
          from >= queue.length ||
          to < 0 ||
          to >= queue.length ||
          from === to
        ) {
          return;
        }

        const newQueue = [...queue];
        const [removed] = newQueue.splice(from, 1);
        newQueue.splice(to, 0, removed);

        // Ajuster l'index courant
        let newIndex = currentIndex;
        if (from === currentIndex) {
          newIndex = to;
        } else if (from < currentIndex && to >= currentIndex) {
          newIndex = currentIndex - 1;
        } else if (from > currentIndex && to <= currentIndex) {
          newIndex = currentIndex + 1;
        }

        set({ queue: newQueue, currentIndex: newIndex });
      },

      clearQueue: () => {
        set({
          queue: [],
          currentIndex: -1,
          currentTrack: null,
          isPlaying: false,
          currentTime: 0,
        });
      },
    }),
    {
      name: 'player-storage',
      partialize: (state) => ({
        volume: state.volume,
        muted: state.muted,
        repeat: state.repeat,
        shuffle: state.shuffle,
        queue: state.queue,
        currentIndex: state.currentIndex,
        currentTrack: state.currentTrack,
      }),
    },
  ),
);
