import { useState, useEffect, useCallback } from 'react'; import { useAuth } from '@clerk/clerk-react'; export interface Collection { id: number; user_id: string; name: string; description?: string; is_public: boolean; cover_asset_id?: number; asset_count: number; created_at: string; updated_at: string; } export interface CollectionCreateRequest { name: string; description?: string; is_public?: boolean; } export interface CollectionUpdateRequest { name?: string; description?: string; is_public?: boolean; cover_asset_id?: number; } const getApiBaseUrl = () => { const url = process.env.REACT_APP_API_URL; if (process.env.NODE_ENV === 'production' && !url) { throw new Error('REACT_APP_API_URL environment variable is required for production'); } return url || 'http://localhost:8000'; }; const API_BASE_URL = getApiBaseUrl(); export const useCollections = () => { const { getToken } = useAuth(); const [collections, setCollections] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const fetchCollections = useCallback(async () => { try { setLoading(true); setError(null); const token = await getToken(); if (!token) { setLoading(false); return; } const response = await fetch(`${API_BASE_URL}/api/content-assets/collections`, { headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, }); if (!response.ok) { throw new Error(`Failed to fetch collections: ${response.statusText}`); } const data = await response.json(); setCollections(data.collections || []); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch collections'); setCollections([]); } finally { setLoading(false); } }, [getToken]); useEffect(() => { fetchCollections(); }, [fetchCollections]); const createCollection = useCallback(async (data: CollectionCreateRequest): Promise => { try { const token = await getToken(); if (!token) { throw new Error('Not authenticated'); } const response = await fetch(`${API_BASE_URL}/api/content-assets/collections`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); if (!response.ok) { throw new Error('Failed to create collection'); } const collection = await response.json(); setCollections(prev => [...prev, collection]); return collection; } catch (err) { console.error('Error creating collection:', err); throw err; } }, [getToken]); const updateCollection = useCallback(async ( collectionId: number, data: CollectionUpdateRequest ): Promise => { try { const token = await getToken(); if (!token) { throw new Error('Not authenticated'); } const response = await fetch(`${API_BASE_URL}/api/content-assets/collections/${collectionId}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); if (!response.ok) { throw new Error('Failed to update collection'); } const collection = await response.json(); setCollections(prev => prev.map(c => c.id === collectionId ? collection : c) ); return collection; } catch (err) { console.error('Error updating collection:', err); throw err; } }, [getToken]); const deleteCollection = useCallback(async (collectionId: number): Promise => { try { const token = await getToken(); if (!token) { throw new Error('Not authenticated'); } const response = await fetch(`${API_BASE_URL}/api/content-assets/collections/${collectionId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, }); if (!response.ok) { throw new Error('Failed to delete collection'); } setCollections(prev => prev.filter(c => c.id !== collectionId)); return true; } catch (err) { console.error('Error deleting collection:', err); throw err; } }, [getToken]); const addAssetsToCollection = useCallback(async ( collectionId: number, assetIds: number[] ): Promise => { try { const token = await getToken(); if (!token) { throw new Error('Not authenticated'); } const response = await fetch(`${API_BASE_URL}/api/content-assets/collections/${collectionId}/assets`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ asset_ids: assetIds }), }); if (!response.ok) { throw new Error('Failed to add assets to collection'); } const result = await response.json(); // Refresh collections to update asset counts await fetchCollections(); return result.assets_added || 0; } catch (err) { console.error('Error adding assets to collection:', err); throw err; } }, [getToken, fetchCollections]); const removeAssetsFromCollection = useCallback(async ( collectionId: number, assetIds: number[] ): Promise => { try { const token = await getToken(); if (!token) { throw new Error('Not authenticated'); } const response = await fetch(`${API_BASE_URL}/api/content-assets/collections/${collectionId}/assets`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ asset_ids: assetIds }), }); if (!response.ok) { throw new Error('Failed to remove assets from collection'); } const result = await response.json(); // Refresh collections to update asset counts await fetchCollections(); return result.assets_removed || 0; } catch (err) { console.error('Error removing assets from collection:', err); throw err; } }, [getToken, fetchCollections]); return { collections, loading, error, refetch: fetchCollections, createCollection, updateCollection, deleteCollection, addAssetsToCollection, removeAssetsFromCollection, }; };