/* eslint-disable */
// @ts-ignore

import type Lenis from "@studio-freight/lenis";
import { Howler } from "howler";
import { type StateCreator } from "zustand";

import type Three from "@/assets/three";
import { type SunoSong, Theme } from "@/types";
import { QUIZ_STEPS, QUIZ_STEPS_VARIANTS } from "@/config/data";

/**
 * Audio Slice
 * ===================================================================
 */

export interface AudioSlice {
  activeAudioEl: HTMLAudioElement | null;
  setActiveAudioEl: (audioEl: HTMLAudioElement | null) => void;
  isMuted: boolean;
  setIsMuted: (isMuted: boolean) => void;
  audioAllowed: boolean;
  setAudioAllowed: (audioAllowed: boolean) => void;
}

export const createAudioSlice: StateCreator<AudioSlice> = (set) => ({
  activeAudioEl: null,
  setActiveAudioEl: (audioEl: HTMLAudioElement | null) => {
    set((state) => {
      if (state.activeAudioEl?.id === audioEl?.id) return state;

      if (state.activeAudioEl && !state.activeAudioEl.paused) {
        state.activeAudioEl.pause();
      }

      return { activeAudioEl: audioEl };
    });
  },
  isMuted: true,
  setIsMuted: (isMuted) => {
    Howler.mute(isMuted);
    set({ isMuted });
  },
  audioAllowed: false,
  setAudioAllowed: (audioAllowed) => {
    if (!audioAllowed) Howler.stop();
    set({ audioAllowed });
  },
});

/**
 * Debug Slice
 * ===================================================================
 */

export interface DebugSlice {
  showDebugClass: boolean;
  setShowDebugClass: (showDebugClass: boolean) => void;
  showDebugMessage: boolean;
  setShowDebugMessage: (showDebugMessage: boolean) => void;
  showAxis: boolean;
  setShowAxis: (showAxis: boolean) => void;
  showStats: boolean;
  setShowStats: (showStats: boolean) => void;
}

export const createDebugSlice: StateCreator<DebugSlice> = (set) => ({
  showDebugClass: false,
  setShowDebugClass: (showDebugClass) => set({ showDebugClass }),
  showDebugMessage: false,
  setShowDebugMessage: (showDebugMessage) => set({ showDebugMessage }),
  showAxis: false,
  setShowAxis: (showAxis) => set({ showAxis }),
  showStats: false,
  setShowStats: (showStats) => set({ showStats }),
});

/**
 * Return User Slice
 * ===================================================================
 */
export interface ReturningUserSlice {
  isReturningUser: boolean;
  setIsReturningUser: (isReturningUser: boolean) => void;
}

export const createReturningUserSlice: StateCreator<ReturningUserSlice> = (
  set,
) => ({
  isReturningUser: false,
  setIsReturningUser: (isReturningUser) => set({ isReturningUser }),
});

/**
 * Quiz Slice
 * ===================================================================
 */

export interface QuizSlice {
  step: number;
  setStep: (step: number) => void;

  lastStep: number;
  setLastStep: (step: number) => void;

  maxStep: number;
  setMaxStep: (maxStep: number) => void;

  language: string;
  setLanguage: (language: string) => void;

  description: string;
  setDescription: (description: string) => void;

  errorWarning: { message: string; input?: HTMLInputElement };
  setErrorWarning: (errorWarning: {
    message: string;
    input?: HTMLInputElement;
  }) => void;

  showErrorWarning: boolean | false;
  setShowErrorWarning: (showErrorWarning: boolean) => void;

  nameTo: string;
  setNameTo: (nameTo: string) => void;

  nameFrom: string;
  setNameFrom: (nameFrom: string) => void;

  emailFrom: string;
  setEmailFrom: (emailFrom: string) => void;

  agreeTC: boolean;
  setAgreeTC: (agreeTC: boolean) => void;

  isGenerating: boolean;
  setIsGenerating: (isGenerating: boolean) => void;

  song: SunoSong;
  setSong: (song: SunoSong) => void;

  songs: Array<SunoSong>;
  setSongs: (songs: Array<SunoSong>) => void;

  carouselDirection: number;
  setCarouselDirection: (carouselDirection: number) => void;

  isRestarting: boolean;
  setIsRestarting: (isRestarting: boolean) => void;

  resetQuiz: (step: number) => void;
}

const initialSong: SunoSong = {
  id: "",
  video_url: "",
  audio_url: "",
  image_url: "",
  metadata: {
    tags: "",
    prompt: "",
    gpt_description_prompt: "",
    type: "",
    duration: 0,
    error_type: "",
  },
  created_at: "",
  status: "",
  title: "",
};

export const createQuizSlice: StateCreator<QuizSlice> = (set) => ({
  step: 0,
  setStep: (step) => set({ step }),

  lastStep: 0,
  setLastStep: (lastStep) => set({ lastStep }),

  maxStep: 0,
  setMaxStep: (maxStep) => set({ maxStep }),

  language: "",
  setLanguage: (language) => set({ language }),

  description: "",
  setDescription: (description) => set({ description }),

  errorWarning: { message: "", input: undefined },
  setErrorWarning: (errorWarning) => set({ errorWarning }),

  showErrorWarning: false,
  setShowErrorWarning: (showErrorWarning) => set({ showErrorWarning }),

  nameTo: "",
  setNameTo: (nameTo) => set({ nameTo }),

  nameFrom: "",
  setNameFrom: (nameFrom) => set({ nameFrom }),

  emailFrom: "",
  setEmailFrom: (emailFrom) => set({ emailFrom }),

  agreeTC: false,
  setAgreeTC: (agreeTC) => set({ agreeTC }),

  isGenerating: false,
  setIsGenerating: (isGenerating) => set({ isGenerating }),

  song: initialSong,
  setSong: (song) => set({ song }),
  songs: [],
  setSongs: (songs) =>
    set(() => ({
      songs: [...songs],
    })),

  carouselDirection: 0,
  setCarouselDirection: (carouselDirection) => set({ carouselDirection }),

  isRestarting: false,
  setIsRestarting: (isRestarting) => set({ isRestarting }),

  resetQuiz: (step) =>
    set((state) => {
      const isResultsStep =
        QUIZ_STEPS[state.step].id === QUIZ_STEPS_VARIANTS.results;
      const singleSong = state.songs.length < 2;

      return {
        step,
        nameTo: "",
        nameFrom: "",
        maxStep: 0,
        language: "",
        description: "",
        errorWarning: { message: "", input: undefined },
        isGenerating: false,
        song: initialSong,
        songs: [],
      };
    }),
});

/**
 * Layout Slice
 * ===================================================================
 */

export interface LayoutSlice {
  lenis: Lenis | null;
  setLenis: (lenis: Lenis | null) => void;
  three: Three | null;
  setThree: (three: Three | null) => void;
  currentTheme: Theme;
  setCurrentTheme: (currentTheme?: Theme) => void;
  currentSectionId: string | null;
  setCurrentSectionId: (currentSectionId: string | null) => void;
  landscape: boolean;
  setLandscape: (landscape: boolean) => void;
  androidKeyboardOverlap: boolean;
  setAndroidKeyboardOverlap: (androidKeyboardOverlap: boolean) => void;
  sectionThemes: Map<string, Theme>;
  updateSectionThemes: (id: string, theme: Theme) => void;
  sectionHeights: Map<string, number>;
  updateSectionHeights: (id: string, element: number) => void;
  sectionRefs: Map<string, HTMLElement | null>;
  updateSectionRefs: (id: string, element: HTMLElement | null) => void;
}

export const createLayoutSlice: StateCreator<LayoutSlice> = (set) => ({
  lenis: null,
  setLenis: (lenis) => set({ lenis }),
  three: null,
  setThree: (three) => set({ three }),
  currentTheme: Theme.Light,
  setCurrentTheme: (currentTheme: Theme = Theme.Light) => set({ currentTheme }),
  currentSectionId: null,
  setCurrentSectionId: (currentSectionId) => set({ currentSectionId }),
  landscape: false,
  androidKeyboardOverlap: false,
  setAndroidKeyboardOverlap: (androidKeyboardOverlap: boolean) =>
    set({ androidKeyboardOverlap }),
  setLandscape: (landscape: boolean) => set({ landscape }),
  sectionThemes: new Map(),
  updateSectionThemes: (id, theme) =>
    set((state) => {
      const updatedMap = new Map(state.sectionThemes);
      updatedMap.set(id, theme);
      return { sectionThemes: updatedMap };
    }),
  sectionHeights: new Map(),
  updateSectionHeights: (id, progress = 0) =>
    set((state) => {
      const updatedMap = new Map(state.sectionHeights);
      updatedMap.set(id, progress);
      return {
        sectionHeights: updatedMap,
      };
    }),
  sectionRefs: new Map(),
  updateSectionRefs: (id, ref = null) =>
    set((state) => {
      const updatedMap = new Map(state.sectionRefs);
      updatedMap.set(id, ref);
      return { sectionRefs: updatedMap };
    }),
});

/**
 * Assets provider Slice
 * ===================================================================
 */

export interface AssetsSlice {
  progress: number;
  setProgress: (progress: number) => void;

  isReady: boolean;
  setIsReady: (isReady: boolean) => void;
}

export const createAssetsSlice: StateCreator<AssetsSlice> = (set) => ({
  progress: 0,
  setProgress: (progress) => set({ progress }),

  isReady: false,
  setIsReady: (isReady) => set({ isReady }),
});
