import { create } from 'zustand'
import { saveSongFiles, loadAllSongFiles, deleteSongFiles } from '../../lib/opfs-storage'
import type { Song } from '../../features/song-select/types'
import type { CustomSongMeta, CustomSongsStore } from './types'

const STORAGE_KEY = 'custom-songs-meta'

function loadMetas(): CustomSongMeta[] {
  try {
    const raw = localStorage.getItem(STORAGE_KEY)
    return raw ? JSON.parse(raw) : []
  } catch {
    return []
  }
}

function saveMetas(metas: CustomSongMeta[]): void {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(metas))
}

function filesToBlobUrls(files: Map<string, File>, meta: CustomSongMeta): Song {
  const audioFile = files.get(meta.audioFile)
  const chartFile = files.get(meta.chartFile)
  const bgFile = files.get(meta.bgFile)
  const bannerFile = files.get(meta.bannerFile)

  return {
    id: meta.id,
    title: meta.title,
    artist: meta.artist,
    bpm: meta.bpm,
    difficulty: meta.difficulty,
    duration: meta.duration,
    genre: meta.genre,
    color: meta.color,
    audioUrl: audioFile ? URL.createObjectURL(audioFile) : '',
    chartUrl: chartFile ? URL.createObjectURL(chartFile) : '',
    bgUrl: bgFile ? URL.createObjectURL(bgFile) : '',
    bannerUrl: bannerFile ? URL.createObjectURL(bannerFile) : '',
    isCustom: true,
    selectedDifficulty: meta.selectedDifficulty,
    simplify: meta.simplify,
  }
}

export const useCustomSongsStore = create<CustomSongsStore>((set) => ({
  songs: [],
  loaded: false,

  async loadStoredSongs() {
    const metas = loadMetas()
    const songs: Song[] = []

    for (const meta of metas) {
      try {
        const files = await loadAllSongFiles(meta.id)
        songs.push(filesToBlobUrls(files, meta))
      } catch {
        // Song files missing from OPFS — skip it
      }
    }

    set({ songs, loaded: true })
  },

  async addSong(meta, files, store) {
    if (store) {
      const buffers: { name: string; data: ArrayBuffer }[] = []
      for (const [name, file] of files) {
        buffers.push({ name, data: await file.arrayBuffer() })
      }
      await saveSongFiles(meta.id, buffers)

      const metas = loadMetas()
      metas.push(meta)
      saveMetas(metas)
    }

    const song = filesToBlobUrls(files, meta)
    set((state) => ({ songs: [...state.songs, song] }))
  },

  async removeSong(id) {
    try { await deleteSongFiles(id) } catch { /* may not be stored */ }
    const metas = loadMetas().filter((m) => m.id !== id)
    saveMetas(metas)
    set((state) => ({
      songs: state.songs.filter((s) => s.id !== id),
    }))
  },
}))
