import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import type { MusicItem } from "@/services/musicSectionService";

type MediaType = "video" | "audio" | "short" | null;

interface PlayerState {
  // ── Shared ──
  type: MediaType;
  isPlaying: boolean;
  volume: number;

  // ── Video state ──
  currentMediaId: string | null;
  title: string;
  thumbnail: string;
  channelName: string;
  duration: number;
  currentTime: number;
  videoUrl: string;
  videoContentUploadType: string;
  isPiP: boolean;

  // ── Audio/Music state ──
  currentTrack: MusicItem | null;
  queue: MusicItem[];
  progress: number; // 0–100
  isShuffle: boolean;
  isRepeat: boolean;
  shuffleHistory: string[];
  audioError: string | null;
}

const initialState: PlayerState = {
  type: null,
  isPlaying: false,
  volume: 80,

  currentMediaId: null,
  title: "",
  thumbnail: "",
  channelName: "",
  duration: 0,
  currentTime: 0,
  videoUrl: "",
  videoContentUploadType: "",
  isPiP: false,

  currentTrack: null,
  queue: [],
  progress: 0,
  isShuffle: false,
  isRepeat: false,
  shuffleHistory: [],
  audioError: null,
};

const playerSlice = createSlice({
  name: "player",
  initialState,
  reducers: {
    // ── VIDEO actions ──────────────────────────────────────────────────────────

    playMedia: (
      state,
      action: PayloadAction<{
        id: string;
        type: MediaType;
        title: string;
        thumbnail: string;
        channelName: string;
        videoUrl?: string;
        videoContentUploadType?: string;
      }>,
    ) => {
      const { id, type, title, thumbnail, channelName, videoUrl, videoContentUploadType } = action.payload;
      state.currentMediaId = id;
      state.type = type;
      state.isPlaying = true;
      state.title = title;
      state.thumbnail = thumbnail;
      state.channelName = channelName;
      state.currentTime = 0;
      state.videoUrl = videoUrl ?? "";
      state.videoContentUploadType = videoContentUploadType ?? "";
      // Stop audio when video takes over
      if (type === "video" || type === "short") {
        state.currentTrack = null;
        state.progress = 0;
      }
    },

    registerMedia: (
      state,
      action: PayloadAction<{
        id: string;
        type: MediaType;
        title: string;
        thumbnail: string;
        channelName: string;
        videoUrl?: string;
        videoContentUploadType?: string;
      }>,
    ) => {
      const { id, type, title, thumbnail, channelName, videoUrl, videoContentUploadType } = action.payload;
      state.currentMediaId = id;
      state.type = type;
      state.isPlaying = false;
      state.title = title;
      state.thumbnail = thumbnail;
      state.channelName = channelName;
      state.currentTime = 0;
      state.videoUrl = videoUrl ?? "";
      state.videoContentUploadType = videoContentUploadType ?? "";
      if (type === "video" || type === "short") {
        state.currentTrack = null;
        state.progress = 0;
      }
    },

    setPiP: (state, action: PayloadAction<boolean>) => {
      state.isPiP = action.payload;
    },

    setCurrentTime: (state, action: PayloadAction<number>) => {
      state.currentTime = action.payload;
    },

    setDuration: (state, action: PayloadAction<number>) => {
      state.duration = action.payload;
    },

    // ── AUDIO actions ──────────────────────────────────────────────────────────

    setTrack: (state, action: PayloadAction<MusicItem>) => {
      state.currentTrack = action.payload;
      state.type = "audio";
      state.isPlaying = true;
      state.progress = 0;
      state.isRepeat = false;
      // Stop video when audio takes over
      state.currentMediaId = null;
      state.videoUrl = "";
    },

    setQueue: (state, action: PayloadAction<MusicItem[]>) => {
      state.queue = action.payload;
    },

    setProgress: (state, action: PayloadAction<number>) => {
      state.progress = action.payload;
    },

    toggleShuffle: (state) => {
      state.isShuffle = !state.isShuffle;
      if (!state.isShuffle) state.shuffleHistory = [];
    },

    toggleRepeat: (state) => {
      state.isRepeat = !state.isRepeat;
    },

    setRepeat: (state, action: PayloadAction<boolean>) => {
      state.isRepeat = action.payload;
    },

    playNext: (state) => {
      if (!state.currentTrack || state.queue.length === 0) return;

      const hasAudio = (item: MusicItem) => !!item.audioUrl?.trim();

      if (state.isRepeat) {
        if (!hasAudio(state.currentTrack)) {
          state.audioError = "Audio not available";
          return;
        }
        state.progress = 0;
        state.isPlaying = true;
        return;
      }

      if (state.isShuffle) {
        const valid = state.queue.filter(hasAudio);
        if (valid.length === 0) { state.audioError = "Audio not available"; return; }
        if (state.shuffleHistory.length >= valid.length) state.shuffleHistory = [];
        const remaining = valid.filter((t) => !state.shuffleHistory.includes(String(t.id)));
        if (remaining.length === 0) return;
        const next = remaining[Math.floor(Math.random() * remaining.length)];
        if (next) {
          state.currentTrack = next;
          state.shuffleHistory.push(String(next.id));
          state.progress = 0;
          state.isPlaying = true;
        }
        return;
      }

      const idx = state.queue.findIndex((t) => t.id === state.currentTrack?.id);
      let next: MusicItem | null = null;
      for (let i = 1; i <= state.queue.length; i++) {
        const candidate = state.queue[(idx + i) % state.queue.length];
        if (candidate && hasAudio(candidate)) { next = candidate; break; }
      }
      if (!next) { state.audioError = "Audio not available"; return; }
      state.currentTrack = next;
      state.progress = 0;
      state.isPlaying = true;
    },

    playPrev: (state) => {
      if (!state.currentTrack || state.queue.length === 0) return;

      const hasAudio = (item: MusicItem) => !!item.audioUrl?.trim();
      const idx = state.queue.findIndex((t) => t.id === state.currentTrack?.id);
      let prev: MusicItem | null = null;
      for (let i = 1; i <= state.queue.length; i++) {
        let prevIdx = idx - i;
        if (prevIdx < 0) prevIdx = state.queue.length + prevIdx;
        const candidate = state.queue[prevIdx];
        if (candidate && hasAudio(candidate)) { prev = candidate; break; }
      }
      if (!prev) { state.audioError = "Audio not available"; return; }
      state.currentTrack = prev;
      state.progress = 0;
      state.isPlaying = true;
    },

    clearAudioError: (state) => {
      state.audioError = null;
    },

    // ── SHARED actions ─────────────────────────────────────────────────────────

    togglePlay: (state) => {
      state.isPlaying = !state.isPlaying;
    },

    setIsPlaying: (state, action: PayloadAction<boolean>) => {
      state.isPlaying = action.payload;
    },

    stopAll: (state) => {
      state.isPlaying = false;
      state.currentMediaId = null;
      state.type = null;
      state.isPiP = false;
      state.currentTrack = null;
      state.progress = 0;
    },

    setVolume: (state, action: PayloadAction<number>) => {
      state.volume = action.payload;
    },
  },
});

export const {
  playMedia,
  registerMedia,
  setPiP,
  setCurrentTime,
  setDuration,
  setTrack,
  setQueue,
  setProgress,
  toggleShuffle,
  toggleRepeat,
  setRepeat,
  playNext,
  playPrev,
  clearAudioError,
  togglePlay,
  setIsPlaying,
  stopAll,
  setVolume,
} = playerSlice.actions;

export default playerSlice.reducer;
