/**
 * AeThex Asset Library - State Store
 * Zustand store for managing game assets
 */

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import {
  Asset,
  AssetFolder,
  AssetFilter,
  AssetSortOptions,
  AssetType,
  AssetCategory,
  AssetUploadOptions,
  getAssetTypeFromFile,
  generateAssetId,
} from '../lib/assets/types';

interface AssetState {
  // Asset data
  assets: Asset[];
  folders: AssetFolder[];

  // UI state
  selectedAssetId: string | null;
  selectedFolderId: string | null;
  viewMode: 'grid' | 'list';
  filter: AssetFilter;
  sort: AssetSortOptions;

  // Actions
  addAsset: (file: File, options?: AssetUploadOptions) => Promise<Asset>;
  removeAsset: (id: string) => void;
  updateAsset: (id: string, updates: Partial<Asset>) => void;
  getAsset: (id: string) => Asset | undefined;

  addFolder: (name: string, parentId?: string) => AssetFolder;
  removeFolder: (id: string) => void;
  updateFolder: (id: string, updates: Partial<AssetFolder>) => void;

  setSelectedAsset: (id: string | null) => void;
  setSelectedFolder: (id: string | null) => void;
  setViewMode: (mode: 'grid' | 'list') => void;
  setFilter: (filter: Partial<AssetFilter>) => void;
  setSort: (sort: AssetSortOptions) => void;
  clearFilter: () => void;

  toggleFavorite: (id: string) => void;
  addTag: (id: string, tag: string) => void;
  removeTag: (id: string, tag: string) => void;

  getFilteredAssets: () => Asset[];
  getAssetsByFolder: (folderId?: string) => Asset[];
  getAssetsByType: (type: AssetType) => Asset[];
  getAssetsByCategory: (category: AssetCategory) => Asset[];
  getFavorites: () => Asset[];
  searchAssets: (query: string) => Asset[];
}

// Helper to create thumbnail from image
async function createImageThumbnail(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d')!;
        const maxSize = 128;
        let width = img.width;
        let height = img.height;

        if (width > height) {
          if (width > maxSize) {
            height *= maxSize / width;
            width = maxSize;
          }
        } else {
          if (height > maxSize) {
            width *= maxSize / height;
            height = maxSize;
          }
        }

        canvas.width = width;
        canvas.height = height;
        ctx.drawImage(img, 0, 0, width, height);
        resolve(canvas.toDataURL('image/jpeg', 0.7));
      };
      img.onerror = reject;
      img.src = e.target?.result as string;
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// Helper to read file as data URL
async function readFileAsDataUrl(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => resolve(e.target?.result as string);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// Helper to get audio metadata
async function getAudioMetadata(file: File): Promise<{ duration: number }> {
  return new Promise((resolve) => {
    const audio = new Audio();
    audio.onloadedmetadata = () => {
      resolve({ duration: audio.duration });
    };
    audio.onerror = () => resolve({ duration: 0 });
    audio.src = URL.createObjectURL(file);
  });
}

// Helper to get image metadata
async function getImageMetadata(file: File): Promise<{ width: number; height: number }> {
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => {
      resolve({ width: img.width, height: img.height });
      URL.revokeObjectURL(img.src);
    };
    img.onerror = () => resolve({ width: 0, height: 0 });
    img.src = URL.createObjectURL(file);
  });
}

export const useAssetStore = create<AssetState>()(
  persist(
    (set, get) => ({
      assets: [],
      folders: [
        { id: 'default', name: 'My Assets', createdAt: new Date() },
      ],
      selectedAssetId: null,
      selectedFolderId: null,
      viewMode: 'grid',
      filter: {},
      sort: { field: 'createdAt', direction: 'desc' },

      addAsset: async (file: File, options?: AssetUploadOptions): Promise<Asset> => {
        const assetType = getAssetTypeFromFile(file);
        const id = generateAssetId();

        // Get metadata based on type
        let metadata: any = {
          fileName: file.name,
          fileSize: file.size,
          mimeType: file.type,
          extension: file.name.split('.').pop()?.toLowerCase() || '',
        };

        let thumbnailUrl: string | undefined;
        let dataUrl: string | undefined;

        // Process based on asset type
        if (assetType === 'texture') {
          const imgMeta = await getImageMetadata(file);
          metadata = { ...metadata, ...imgMeta };
          thumbnailUrl = await createImageThumbnail(file);
          if (file.size < 5 * 1024 * 1024) { // Under 5MB, store as data URL
            dataUrl = await readFileAsDataUrl(file);
          }
        } else if (assetType === 'audio') {
          const audioMeta = await getAudioMetadata(file);
          metadata = { ...metadata, ...audioMeta };
          if (file.size < 10 * 1024 * 1024) { // Under 10MB
            dataUrl = await readFileAsDataUrl(file);
          }
        } else if (file.size < 5 * 1024 * 1024) {
          dataUrl = await readFileAsDataUrl(file);
        }

        const asset: Asset = {
          id,
          name: options?.name || file.name.replace(/\.[^.]+$/, ''),
          type: assetType,
          category: options?.category || 'uncategorized',
          tags: options?.tags || [],
          file,
          dataUrl,
          thumbnailUrl,
          metadata,
          folderId: options?.folderId || 'default',
          favorite: false,
          createdAt: new Date(),
          updatedAt: new Date(),
          platforms: ['universal'],
        };

        set((state) => ({
          assets: [...state.assets, asset],
        }));

        return asset;
      },

      removeAsset: (id: string) => {
        const asset = get().assets.find((a) => a.id === id);
        if (asset?.blobUrl) {
          URL.revokeObjectURL(asset.blobUrl);
        }
        set((state) => ({
          assets: state.assets.filter((a) => a.id !== id),
          selectedAssetId: state.selectedAssetId === id ? null : state.selectedAssetId,
        }));
      },

      updateAsset: (id: string, updates: Partial<Asset>) => {
        set((state) => ({
          assets: state.assets.map((a) =>
            a.id === id ? { ...a, ...updates, updatedAt: new Date() } : a
          ),
        }));
      },

      getAsset: (id: string) => {
        return get().assets.find((a) => a.id === id);
      },

      addFolder: (name: string, parentId?: string): AssetFolder => {
        const folder: AssetFolder = {
          id: `folder-${Date.now()}`,
          name,
          parentId,
          createdAt: new Date(),
        };
        set((state) => ({
          folders: [...state.folders, folder],
        }));
        return folder;
      },

      removeFolder: (id: string) => {
        set((state) => ({
          folders: state.folders.filter((f) => f.id !== id),
          assets: state.assets.map((a) =>
            a.folderId === id ? { ...a, folderId: 'default' } : a
          ),
          selectedFolderId: state.selectedFolderId === id ? null : state.selectedFolderId,
        }));
      },

      updateFolder: (id: string, updates: Partial<AssetFolder>) => {
        set((state) => ({
          folders: state.folders.map((f) =>
            f.id === id ? { ...f, ...updates } : f
          ),
        }));
      },

      setSelectedAsset: (id: string | null) => set({ selectedAssetId: id }),
      setSelectedFolder: (id: string | null) => set({ selectedFolderId: id }),
      setViewMode: (mode: 'grid' | 'list') => set({ viewMode: mode }),

      setFilter: (filter: Partial<AssetFilter>) => {
        set((state) => ({
          filter: { ...state.filter, ...filter },
        }));
      },

      setSort: (sort: AssetSortOptions) => set({ sort }),

      clearFilter: () => set({ filter: {} }),

      toggleFavorite: (id: string) => {
        set((state) => ({
          assets: state.assets.map((a) =>
            a.id === id ? { ...a, favorite: !a.favorite } : a
          ),
        }));
      },

      addTag: (id: string, tag: string) => {
        set((state) => ({
          assets: state.assets.map((a) =>
            a.id === id && !a.tags.includes(tag)
              ? { ...a, tags: [...a.tags, tag] }
              : a
          ),
        }));
      },

      removeTag: (id: string, tag: string) => {
        set((state) => ({
          assets: state.assets.map((a) =>
            a.id === id ? { ...a, tags: a.tags.filter((t) => t !== tag) } : a
          ),
        }));
      },

      getFilteredAssets: () => {
        const { assets, filter, sort } = get();
        let filtered = [...assets];

        // Apply filters
        if (filter.type) {
          const types = Array.isArray(filter.type) ? filter.type : [filter.type];
          filtered = filtered.filter((a) => types.includes(a.type));
        }

        if (filter.category) {
          const categories = Array.isArray(filter.category)
            ? filter.category
            : [filter.category];
          filtered = filtered.filter((a) => categories.includes(a.category));
        }

        if (filter.tags && filter.tags.length > 0) {
          filtered = filtered.filter((a) =>
            filter.tags!.some((tag) => a.tags.includes(tag))
          );
        }

        if (filter.folderId) {
          filtered = filtered.filter((a) => a.folderId === filter.folderId);
        }

        if (filter.favorite !== undefined) {
          filtered = filtered.filter((a) => a.favorite === filter.favorite);
        }

        if (filter.search) {
          const query = filter.search.toLowerCase();
          filtered = filtered.filter(
            (a) =>
              a.name.toLowerCase().includes(query) ||
              a.tags.some((t) => t.toLowerCase().includes(query)) ||
              a.description?.toLowerCase().includes(query)
          );
        }

        // Apply sorting
        filtered.sort((a, b) => {
          let comparison = 0;
          switch (sort.field) {
            case 'name':
              comparison = a.name.localeCompare(b.name);
              break;
            case 'createdAt':
              comparison = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
              break;
            case 'updatedAt':
              comparison = new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
              break;
            case 'fileSize':
              comparison = a.metadata.fileSize - b.metadata.fileSize;
              break;
            case 'type':
              comparison = a.type.localeCompare(b.type);
              break;
          }
          return sort.direction === 'asc' ? comparison : -comparison;
        });

        return filtered;
      },

      getAssetsByFolder: (folderId?: string) => {
        return get().assets.filter((a) => a.folderId === (folderId || 'default'));
      },

      getAssetsByType: (type: AssetType) => {
        return get().assets.filter((a) => a.type === type);
      },

      getAssetsByCategory: (category: AssetCategory) => {
        return get().assets.filter((a) => a.category === category);
      },

      getFavorites: () => {
        return get().assets.filter((a) => a.favorite);
      },

      searchAssets: (query: string) => {
        const lowerQuery = query.toLowerCase();
        return get().assets.filter(
          (a) =>
            a.name.toLowerCase().includes(lowerQuery) ||
            a.tags.some((t) => t.toLowerCase().includes(lowerQuery))
        );
      },
    }),
    {
      name: 'aethex-assets',
      partialize: (state) => ({
        assets: state.assets.map((a) => ({
          ...a,
          file: undefined, // Don't persist File objects
          blobUrl: undefined, // Don't persist blob URLs
        })),
        folders: state.folders,
        viewMode: state.viewMode,
        sort: state.sort,
      }),
    }
  )
);
