import { create } from 'zustand';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Track, Playlist } from '../types';

const LIBRARY_STORAGE_KEY = '@vinyl_library';
const PLAYLISTS_STORAGE_KEY = '@vinyl_playlists';

interface LibraryStore {
  // State
  tracks: Track[];
  playlists: Playlist[];
  isLoading: boolean;

  // Track actions
  loadLibrary: () => Promise<void>;
  addTrack: (track: Track) => Promise<void>;
  addTracks: (tracks: Track[]) => Promise<void>;
  removeTrack: (trackId: string) => Promise<void>;
  updateTrack: (trackId: string, updates: Partial<Track>) => Promise<void>;

  // Playlist actions
  createPlaylist: (name: string) => Promise<Playlist>;
  deletePlaylist: (playlistId: string) => Promise<void>;
  renamePlaylist: (playlistId: string, name: string) => Promise<void>;
  addToPlaylist: (playlistId: string, trackId: string) => Promise<void>;
  removeFromPlaylist: (playlistId: string, trackId: string) => Promise<void>;
  reorderPlaylist: (playlistId: string, trackIds: string[]) => Promise<void>;

  // Utility
  getPlaylistTracks: (playlistId: string) => Track[];
}

// Generate unique ID
const generateId = () => Math.random().toString(36).substring(2, 15);

export const useLibraryStore = create<LibraryStore>((set, get) => ({
  tracks: [],
  playlists: [],
  isLoading: true,

  loadLibrary: async () => {
    try {
      const [tracksJson, playlistsJson] = await Promise.all([
        AsyncStorage.getItem(LIBRARY_STORAGE_KEY),
        AsyncStorage.getItem(PLAYLISTS_STORAGE_KEY),
      ]);

      const tracks = tracksJson ? JSON.parse(tracksJson) : [];
      const playlists = playlistsJson ? JSON.parse(playlistsJson) : [];

      set({ tracks, playlists, isLoading: false });
    } catch (error) {
      console.error('Failed to load library:', error);
      set({ isLoading: false });
    }
  },

  addTrack: async (track) => {
    const { tracks } = get();
    // Check for duplicate by URL
    if (tracks.some((t) => t.url === track.url)) {
      return; // Already exists
    }
    const newTracks = [...tracks, { ...track, id: track.id || generateId() }];
    set({ tracks: newTracks });
    await AsyncStorage.setItem(LIBRARY_STORAGE_KEY, JSON.stringify(newTracks));
  },

  addTracks: async (newTracksToAdd) => {
    const { tracks } = get();
    const existingUrls = new Set(tracks.map((t) => t.url));
    const uniqueNewTracks = newTracksToAdd
      .filter((t) => !existingUrls.has(t.url))
      .map((t) => ({ ...t, id: t.id || generateId() }));

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

    const newTracks = [...tracks, ...uniqueNewTracks];
    set({ tracks: newTracks });
    await AsyncStorage.setItem(LIBRARY_STORAGE_KEY, JSON.stringify(newTracks));
  },

  removeTrack: async (trackId) => {
    const { tracks, playlists } = get();
    const newTracks = tracks.filter((t) => t.id !== trackId);
    // Also remove from all playlists
    const newPlaylists = playlists.map((p) => ({
      ...p,
      trackIds: p.trackIds.filter((id) => id !== trackId),
      updatedAt: Date.now(),
    }));

    set({ tracks: newTracks, playlists: newPlaylists });
    await Promise.all([
      AsyncStorage.setItem(LIBRARY_STORAGE_KEY, JSON.stringify(newTracks)),
      AsyncStorage.setItem(PLAYLISTS_STORAGE_KEY, JSON.stringify(newPlaylists)),
    ]);
  },

  updateTrack: async (trackId, updates) => {
    const { tracks } = get();
    const newTracks = tracks.map((t) =>
      t.id === trackId ? { ...t, ...updates } : t
    );
    set({ tracks: newTracks });
    await AsyncStorage.setItem(LIBRARY_STORAGE_KEY, JSON.stringify(newTracks));
  },

  createPlaylist: async (name) => {
    const { playlists } = get();
    const newPlaylist: Playlist = {
      id: generateId(),
      name,
      trackIds: [],
      createdAt: Date.now(),
      updatedAt: Date.now(),
    };
    const newPlaylists = [...playlists, newPlaylist];
    set({ playlists: newPlaylists });
    await AsyncStorage.setItem(
      PLAYLISTS_STORAGE_KEY,
      JSON.stringify(newPlaylists)
    );
    return newPlaylist;
  },

  deletePlaylist: async (playlistId) => {
    const { playlists } = get();
    const newPlaylists = playlists.filter((p) => p.id !== playlistId);
    set({ playlists: newPlaylists });
    await AsyncStorage.setItem(
      PLAYLISTS_STORAGE_KEY,
      JSON.stringify(newPlaylists)
    );
  },

  renamePlaylist: async (playlistId, name) => {
    const { playlists } = get();
    const newPlaylists = playlists.map((p) =>
      p.id === playlistId ? { ...p, name, updatedAt: Date.now() } : p
    );
    set({ playlists: newPlaylists });
    await AsyncStorage.setItem(
      PLAYLISTS_STORAGE_KEY,
      JSON.stringify(newPlaylists)
    );
  },

  addToPlaylist: async (playlistId, trackId) => {
    const { playlists } = get();
    const newPlaylists = playlists.map((p) => {
      if (p.id === playlistId && !p.trackIds.includes(trackId)) {
        return {
          ...p,
          trackIds: [...p.trackIds, trackId],
          updatedAt: Date.now(),
        };
      }
      return p;
    });
    set({ playlists: newPlaylists });
    await AsyncStorage.setItem(
      PLAYLISTS_STORAGE_KEY,
      JSON.stringify(newPlaylists)
    );
  },

  removeFromPlaylist: async (playlistId, trackId) => {
    const { playlists } = get();
    const newPlaylists = playlists.map((p) => {
      if (p.id === playlistId) {
        return {
          ...p,
          trackIds: p.trackIds.filter((id) => id !== trackId),
          updatedAt: Date.now(),
        };
      }
      return p;
    });
    set({ playlists: newPlaylists });
    await AsyncStorage.setItem(
      PLAYLISTS_STORAGE_KEY,
      JSON.stringify(newPlaylists)
    );
  },

  reorderPlaylist: async (playlistId, trackIds) => {
    const { playlists } = get();
    const newPlaylists = playlists.map((p) =>
      p.id === playlistId ? { ...p, trackIds, updatedAt: Date.now() } : p
    );
    set({ playlists: newPlaylists });
    await AsyncStorage.setItem(
      PLAYLISTS_STORAGE_KEY,
      JSON.stringify(newPlaylists)
    );
  },

  getPlaylistTracks: (playlistId) => {
    const { tracks, playlists } = get();
    const playlist = playlists.find((p) => p.id === playlistId);
    if (!playlist) return [];
    return playlist.trackIds
      .map((id) => tracks.find((t) => t.id === id))
      .filter(Boolean) as Track[];
  },
}));
