'use client';

import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';
import type { MediaAsset, AmsoilImage, ImageSelection, MediaContext, MediaUsage } from '@/types/media';
import { isPdfMimeType } from '@/lib/media-utils';
import { uploadFile } from '@/lib/upload-file';

interface MediaLibraryState {
  myImages: MediaAsset[];
  amsoilImages: AmsoilImage[];
  imageUsage: MediaUsage;
  documentUsage: MediaUsage;
  isLoading: boolean;
  error: string | null;
  selectedImage: ImageSelection | null;
  activeTab: 'my-images' | 'my-documents' | 'amsoil';
  uploadProgress: number | null;
}

interface MediaLibraryContextType extends MediaLibraryState {
  // Actions
  fetchMedia: () => Promise<void>;
  uploadImage: (file: File, context?: MediaContext, alt?: string) => Promise<MediaAsset | null>;
  deleteImage: (id: string) => Promise<boolean>;
  updateImage: (id: string, updates: { alt?: string; context?: MediaContext }) => Promise<boolean>;
  selectImage: (image: ImageSelection | null) => void;
  setActiveTab: (tab: 'my-images' | 'my-documents' | 'amsoil') => void;
  clearError: () => void;
}

const MediaLibraryContext = createContext<MediaLibraryContextType | null>(null);

export function useMediaLibrary() {
  const context = useContext(MediaLibraryContext);
  if (!context) {
    throw new Error('useMediaLibrary must be used within a MediaLibraryProvider');
  }
  return context;
}

interface MediaLibraryProviderProps {
  children: React.ReactNode;
}

export function MediaLibraryProvider({ children }: MediaLibraryProviderProps) {
  const [state, setState] = useState<MediaLibraryState>({
    myImages: [],
    amsoilImages: [],
    imageUsage: { current: 0, limit: 0 },
    documentUsage: { current: 0, limit: 0 },
    isLoading: true,
    error: null,
    selectedImage: null,
    activeTab: 'my-images',
    uploadProgress: null,
  });

  const fetchMedia = useCallback(async () => {
    setState((prev) => ({ ...prev, isLoading: true, error: null }));

    try {
      const response = await fetch('/api/media');

      if (!response.ok) {
        const data = await response.json();
        throw new Error(data.error || 'Failed to fetch media');
      }

      const data = await response.json();

      setState((prev) => ({
        ...prev,
        myImages: data.myImages,
        amsoilImages: data.amsoilImages,
        imageUsage: data.imageUsage,
        documentUsage: data.documentUsage,
        isLoading: false,
      }));
    } catch (error) {
      setState((prev) => ({
        ...prev,
        isLoading: false,
        error: error instanceof Error ? error.message : 'Failed to fetch media',
      }));
    }
  }, []);

  const uploadImage = useCallback(
    async (
      file: File,
      context: MediaContext = 'general',
      alt?: string
    ): Promise<MediaAsset | null> => {
      setState((prev) => ({ ...prev, uploadProgress: 0, error: null }));

      try {
        const response = await uploadFile({
          file,
          context,
          alt: alt || undefined,
          onProgress: (percent) => {
            setState((prev) => ({ ...prev, uploadProgress: percent }));
          },
        });

        if (!response.ok) {
          const data = await response.json();
          throw new Error(data.error || 'Failed to upload file');
        }

        const data = await response.json();

        setState((prev) => ({
          ...prev,
          myImages: [data.asset, ...prev.myImages],
          ...(data.imageUsage && { imageUsage: data.imageUsage }),
          ...(data.documentUsage && { documentUsage: data.documentUsage }),
          uploadProgress: null,
        }));

        return data.asset;
      } catch (error) {
        setState((prev) => ({
          ...prev,
          uploadProgress: null,
          error: error instanceof Error ? error.message : 'Failed to upload file',
        }));
        return null;
      }
    },
    []
  );

  const deleteImage = useCallback(async (id: string): Promise<boolean> => {
    try {
      const response = await fetch(`/api/media/${id}`, {
        method: 'DELETE',
      });

      if (!response.ok) {
        const data = await response.json();
        throw new Error(data.error || 'Failed to delete image');
      }

      setState((prev) => {
        const deletedAsset = prev.myImages.find((img) => img.id === id);
        const isDoc = deletedAsset ? isPdfMimeType(deletedAsset.mimeType) : false;
        return {
          ...prev,
          myImages: prev.myImages.filter((img) => img.id !== id),
          imageUsage: isDoc
            ? prev.imageUsage
            : { ...prev.imageUsage, current: prev.imageUsage.current - 1 },
          documentUsage: isDoc
            ? { ...prev.documentUsage, current: prev.documentUsage.current - 1 }
            : prev.documentUsage,
          selectedImage: prev.selectedImage?.id === id ? null : prev.selectedImage,
        };
      });

      return true;
    } catch (error) {
      setState((prev) => ({
        ...prev,
        error: error instanceof Error ? error.message : 'Failed to delete image',
      }));
      return false;
    }
  }, []);

  const updateImage = useCallback(
    async (id: string, updates: { alt?: string; context?: MediaContext }): Promise<boolean> => {
      try {
        const response = await fetch(`/api/media/${id}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(updates),
        });

        if (!response.ok) {
          const data = await response.json();
          throw new Error(data.error || 'Failed to update image');
        }

        const updatedAsset = await response.json();

        setState((prev) => ({
          ...prev,
          myImages: prev.myImages.map((img) => (img.id === id ? updatedAsset : img)),
        }));

        return true;
      } catch (error) {
        setState((prev) => ({
          ...prev,
          error: error instanceof Error ? error.message : 'Failed to update image',
        }));
        return false;
      }
    },
    []
  );

  const selectImage = useCallback((image: ImageSelection | null) => {
    setState((prev) => ({ ...prev, selectedImage: image }));
  }, []);

  const setActiveTab = useCallback((tab: 'my-images' | 'my-documents' | 'amsoil') => {
    setState((prev) => ({ ...prev, activeTab: tab }));
  }, []);

  const clearError = useCallback(() => {
    setState((prev) => ({ ...prev, error: null }));
  }, []);

  // Fetch media on mount
  useEffect(() => {
    fetchMedia();
  }, [fetchMedia]);

  const value: MediaLibraryContextType = {
    ...state,
    fetchMedia,
    uploadImage,
    deleteImage,
    updateImage,
    selectImage,
    setActiveTab,
    clearError,
  };

  return <MediaLibraryContext.Provider value={value}>{children}</MediaLibraryContext.Provider>;
}
