import { useState, useCallback, useEffect } from "react"; import { listFileVersions, getFileVersion, restoreFileVersion, type FileVersionSummary, type FileVersion, type FileDetail, VersionConflictError, } from "../lib/api"; export interface UseVersionHistoryOptions { fileId: string | null; currentVersion: number; } export interface VersionHistoryState { versions: FileVersionSummary[]; loading: boolean; error: string | null; selectedVersion: FileVersion | null; loadingVersion: boolean; } export function useVersionHistory(options: UseVersionHistoryOptions) { const { fileId, currentVersion } = options; const [versions, setVersions] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [selectedVersion, setSelectedVersion] = useState(null); const [loadingVersion, setLoadingVersion] = useState(false); const [restoring, setRestoring] = useState(false); const [conflict, setConflict] = useState<{ expected: number; actual: number } | null>(null); // Fetch version list const fetchVersions = useCallback(async () => { if (!fileId) return; setLoading(true); setError(null); try { const response = await listFileVersions(fileId); setVersions(response.versions); } catch (e) { setError(e instanceof Error ? e.message : "Failed to fetch versions"); } finally { setLoading(false); } }, [fileId]); // Fetch a specific version's content const fetchVersion = useCallback( async (version: number): Promise => { if (!fileId) return null; setLoadingVersion(true); setError(null); try { const versionData = await getFileVersion(fileId, version); setSelectedVersion(versionData); return versionData; } catch (e) { setError(e instanceof Error ? e.message : "Failed to fetch version"); return null; } finally { setLoadingVersion(false); } }, [fileId] ); // Restore to a specific version (creates a new version with that content) const restoreToVersion = useCallback( async (targetVersion: number): Promise => { if (!fileId) return null; setRestoring(true); setError(null); setConflict(null); try { const result = await restoreFileVersion(fileId, targetVersion, currentVersion); // Refresh version list after restore await fetchVersions(); setSelectedVersion(null); return result; } catch (e) { if (e instanceof VersionConflictError) { setConflict({ expected: e.expectedVersion, actual: e.actualVersion, }); return null; } setError(e instanceof Error ? e.message : "Failed to restore version"); return null; } finally { setRestoring(false); } }, [fileId, currentVersion, fetchVersions] ); // Clear selected version const clearSelectedVersion = useCallback(() => { setSelectedVersion(null); }, []); // Clear conflict const clearConflict = useCallback(() => { setConflict(null); }, []); // Fetch versions when fileId changes useEffect(() => { if (fileId) { fetchVersions(); } else { setVersions([]); setSelectedVersion(null); } }, [fileId, fetchVersions]); return { versions, loading, error, selectedVersion, loadingVersion, restoring, conflict, fetchVersions, fetchVersion, restoreToVersion, clearSelectedVersion, clearConflict, }; }