import { create } from 'zustand';
import { persist, devtools } from 'zustand/middleware';
import { apiClient } from '@/services/api/client';
import { undoRedo } from '@/utils/undoRedo';
import { stateMiddleware } from '@/utils/stateMiddleware';
import {
  normalize,
  addToNormalized,
  updateInNormalized,
  removeFromNormalized,
  createEmptyNormalized,
  type NormalizedState,
} from '@/utils/stateNormalization';
import type { LibraryItem, PaginatedResponse, ApiError } from '@/types';
import type { WithUndoRedo } from './types';

// FE-TYPE-011: Fully typed store interfaces
export interface LibraryState {
  // FE-STATE-009: Normalized state for better performance
  items: NormalizedState<LibraryItem>;
  favorites: NormalizedState<LibraryItem>;
  isLoading: boolean;
  error: ApiError | null;
  pagination: {
    page: number;
    limit: number;
    total: number;
    hasNext: boolean;
    hasPrev: boolean;
  };
  filters: {
    type?: string;
    search?: string;
  };
}

export interface LibraryActions {
  fetchItems: (params?: {
    page?: number;
    limit?: number;
    type?: string;
    search?: string;
  }) => Promise<void>;
  fetchFavorites: () => Promise<void>;
  uploadFile: (
    file: File,
    metadata: { title: string; description?: string },
  ) => Promise<void>;
  toggleFavorite: (itemId: string) => Promise<void>;
  deleteItem: (itemId: string) => Promise<void>;
  setFilters: (filters: { type?: string; search?: string }) => void;
  setLoading: (loading: boolean) => void;
  setError: (error: ApiError | null) => void;
  clearItems: () => void;
}

// FE-TYPE-011: Export store type for reuse
export type LibraryStore = WithUndoRedo<LibraryState & LibraryActions>;

export const useLibraryStore = create<LibraryStore>()(
  devtools(
    persist(
      undoRedo(
        stateMiddleware(
          (set, get) => ({
    // État initial - FE-STATE-009: Normalized state
    items: createEmptyNormalized<LibraryItem>(),
    favorites: createEmptyNormalized<LibraryItem>(),
    isLoading: false,
    error: null,
    pagination: {
      page: 1,
      limit: 20,
      total: 0,
      hasNext: false,
      hasPrev: false,
    },
    filters: {},

    // Actions
    fetchItems: async (params = {}) => {
      set({ isLoading: true, error: null });
      try {
        const {
          page = 1,
          limit = 20,
          type,
        } = { ...get().pagination, ...get().filters, ...params };

        const response = await apiClient.get<PaginatedResponse<LibraryItem>>('/tracks', {
          params: {
            page,
            limit,
            type,
          },
        });

        // apiClient unwrap déjà le format { success, data }, donc response.data contient directement la réponse
        const data = response.data;
        // Sécuriser response.data pour s'assurer que c'est toujours un tableau
        const itemsArray = Array.isArray(data.data) 
          ? data.data 
          : Array.isArray(data) 
            ? data 
            : [];

        // FE-STATE-009: Normalize items for better performance
        set({
          items: normalize(itemsArray),
          pagination: {
            page: data.page || 1,
            limit: data.limit || limit,
            total: data.total || 0,
            hasNext: data.has_next || false,
            hasPrev: data.has_prev || false,
          },
          isLoading: false,
          error: null,
        });
      } catch (error: any) {
        // En cas d'erreur, s'assurer que items reste un état normalisé vide
        set({
          items: createEmptyNormalized<LibraryItem>(),
          error: error as ApiError,
          isLoading: false,
        });
      }
    },

    fetchFavorites: async () => {
      set({ isLoading: true, error: null });
      try {
        const response = await apiClient.get<PaginatedResponse<LibraryItem>>('/tracks', {
          params: {
            page: 1,
            limit: 100,
            type: 'favorites',
          },
        });

        // apiClient unwrap déjà le format { success, data }, donc response.data contient directement la réponse
        const data = response.data;
        // Sécuriser response.data pour s'assurer que c'est toujours un tableau
        const favoritesArray = Array.isArray(data.data) 
          ? data.data 
          : Array.isArray(data) 
            ? data 
            : [];

        // FE-STATE-009: Normalize favorites for better performance
        set({
          favorites: normalize(favoritesArray),
          isLoading: false,
          error: null,
        });
      } catch (error: any) {
        // En cas d'erreur, s'assurer que favorites reste un état normalisé vide
        set({
          favorites: createEmptyNormalized<LibraryItem>(),
          error: error as ApiError,
          isLoading: false,
        });
      }
    },

    uploadFile: async (file, metadata) => {
      set({ isLoading: true, error: null });
      try {
        const formData = new FormData();
        formData.append('file', file);
        formData.append('title', metadata.title);
        if (metadata.description) {
          formData.append('description', metadata.description);
        }

        const response = await apiClient.post<LibraryItem>('/tracks', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        });
        const newItem = response.data;

        // FE-STATE-009: Add to normalized state at position 0 (prepend)
        set((state) => ({
          items: addToNormalized(state.items, newItem, 0),
          isLoading: false,
          error: null,
        }));
      } catch (error: any) {
        set({
          error: error as ApiError,
          isLoading: false,
        });
        throw error;
      }
    },

    // FE-STATE-005: Optimistic update for toggle favorite
    // FE-STATE-009: Using normalized state operations
    toggleFavorite: async (itemId: string) => {
      const previousState = get();
      const item = previousState.items.byId[itemId];
      const newFavoriteStatus = item ? !item.is_favorite : true;

      // Optimistic update - FE-STATE-009: Update in normalized state
      set((state) => {
        const updatedItems = updateInNormalized(state.items, itemId, {
          is_favorite: newFavoriteStatus,
        });
        
        let updatedFavorites = state.favorites;
        if (newFavoriteStatus && item) {
          // Add to favorites
          const favoriteItem = { ...item, is_favorite: true };
          updatedFavorites = addToNormalized(
            removeFromNormalized(state.favorites, itemId),
            favoriteItem,
          );
        } else {
          // Remove from favorites
          updatedFavorites = removeFromNormalized(state.favorites, itemId);
        }

        return {
          items: updatedItems,
          favorites: updatedFavorites,
        };
      });

      try {
        const response = await apiClient.post<LibraryItem>(`/tracks/${itemId}/favorite`);
        const updatedItem = response.data;

        // Apply server response - FE-STATE-009: Update in normalized state
        set((state) => {
          const updatedItems = updateInNormalized(state.items, itemId, {
            is_favorite: updatedItem.is_favorite,
          });
          
          let updatedFavorites = state.favorites;
          if (updatedItem.is_favorite) {
            updatedFavorites = addToNormalized(
              removeFromNormalized(state.favorites, itemId),
              updatedItem,
            );
          } else {
            updatedFavorites = removeFromNormalized(state.favorites, itemId);
          }

          return {
            items: updatedItems,
            favorites: updatedFavorites,
          };
        });
      } catch (error: any) {
        // Rollback on error
        set(() => previousState);
        set({ error: error as ApiError });
        throw error;
      }
    },

    // FE-STATE-005: Optimistic update for delete item
    // FE-STATE-009: Using normalized state operations
    deleteItem: async (itemId: string) => {
      const previousState = get();

      // Optimistic update - remove item immediately from normalized state
      set((state) => ({
        items: removeFromNormalized(state.items, itemId),
        favorites: removeFromNormalized(state.favorites, itemId),
      }));

      try {
        // Appel API pour supprimer l'élément
        await apiClient.delete(`/tracks/${itemId}`);
        // No need to update state - optimistic update is final
      } catch (error: any) {
        // Rollback on error
        set(() => previousState);
        set({ error: error as ApiError });
        throw error;
      }
    },

    setFilters: (filters) => {
      set({ filters });
      // Recharger les éléments avec les nouveaux filtres
      get().fetchItems({ page: 1 });
    },

    setLoading: (isLoading) => set({ isLoading }),

    setError: (error) => set({ error }),

    clearItems: () => {
      set({
        items: createEmptyNormalized<LibraryItem>(),
        favorites: createEmptyNormalized<LibraryItem>(),
        pagination: {
          page: 1,
          limit: 20,
          total: 0,
          hasNext: false,
          hasPrev: false,
        },
      });
    },
          }),
          {
            // FE-STATE-010: Enable state middleware for logging, analytics, error handling
            storeName: 'LibraryStore',
            enableLogging: import.meta.env.DEV,
            enableAnalytics: true,
            enableErrorHandling: true,
          },
        ),
        {
          // FE-STATE-006: Enable undo/redo for library store
        maxHistorySize: 50,
        enabled: true,
        shouldTrack: (state, prevState) => {
          // Track changes to items and favorites (not loading/error states)
          // FE-STATE-009: Compare normalized state structures
          return (
            JSON.stringify(state.items) !== JSON.stringify(prevState?.items) ||
            JSON.stringify(state.favorites) !== JSON.stringify(prevState?.favorites)
          );
        },
      },
    ),
    {
      name: 'library-storage',
        partialize: (state) => ({
          // FE-STATE-001: Persist favorites and filters for offline support
          // FE-STATE-009: Persist normalized favorites state
          favorites: state.favorites,
          filters: state.filters,
          // Don't persist items and pagination as they should be fetched fresh
        }),
      },
    ),
    {
      // FE-STATE-007: Enable Redux DevTools for debugging
      name: 'LibraryStore',
      enabled: import.meta.env.DEV,
    },
  ),
);
