import { useCallback, useEffect, useState } from 'react' import { invoke } from '@tauri-apps/api/core' import { isTauri, mockInvoke } from '../mock-tauri' import type { VaultEntry, GitCommit, ModifiedFile } from '../types' function tauriCall(command: string, tauriArgs: Record, mockArgs?: Record): Promise { return isTauri() ? invoke(command, tauriArgs) : mockInvoke(command, mockArgs ?? tauriArgs) } async function loadVaultData(vaultPath: string) { if (!isTauri()) console.info('[mock] Using mock Tauri data for browser testing') const entries = await tauriCall('list_vault', { path: vaultPath }) console.log(`Vault scan complete: ${entries.length} entries found`) const allContent = isTauri() ? {} : await mockInvoke>('get_all_content', { path: vaultPath }) return { entries, allContent } } async function commitWithPush(vaultPath: string, message: string): Promise { if (!isTauri()) { await mockInvoke('git_commit', { message }) await mockInvoke('git_push', {}) return 'Committed and pushed' } await invoke('git_commit', { vaultPath, message }) try { await invoke('git_push', { vaultPath }) return 'Committed and pushed' } catch { return 'Committed (push failed)' } } export function useVaultLoader(vaultPath: string) { const [entries, setEntries] = useState([]) const [allContent, setAllContent] = useState>({}) const [modifiedFiles, setModifiedFiles] = useState([]) useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect -- clear stale data then load new vault setEntries([]); setAllContent({}); setModifiedFiles([]) loadVaultData(vaultPath) .then(({ entries: e, allContent: c }) => { setEntries(e); setAllContent(c) }) .catch((err) => console.warn('Vault scan failed:', err)) }, [vaultPath]) const loadModifiedFiles = useCallback(async () => { try { setModifiedFiles(await tauriCall('get_modified_files', { vaultPath }, {})) } catch (err) { console.warn('Failed to load modified files:', err) setModifiedFiles([]) } }, [vaultPath]) useEffect(() => { loadModifiedFiles() }, [loadModifiedFiles]) // eslint-disable-line react-hooks/set-state-in-effect -- trigger initial load const addEntry = useCallback((entry: VaultEntry, content: string) => { setEntries((prev) => [entry, ...prev]) setAllContent((prev) => ({ ...prev, [entry.path]: content })) }, []) const updateContent = useCallback((path: string, content: string) => { setAllContent((prev) => ({ ...prev, [path]: content })) }, []) const updateEntry = useCallback((path: string, patch: Partial) => { setEntries((prev) => prev.map((e) => e.path === path ? { ...e, ...patch } : e)) }, []) const replaceEntry = useCallback((oldPath: string, patch: Partial & { path: string }, newContent: string) => { setEntries((prev) => prev.map((e) => e.path === oldPath ? { ...e, ...patch } : e)) setAllContent((prev) => { const next = { ...prev } delete next[oldPath] next[patch.path] = newContent return next }) }, []) const loadGitHistory = useCallback(async (path: string): Promise => { try { return await tauriCall('get_file_history', { vaultPath, path }, { path }) } catch (err) { console.warn('Failed to load git history:', err); return [] } }, [vaultPath]) const loadDiffAtCommit = useCallback((path: string, commitHash: string): Promise => tauriCall('get_file_diff_at_commit', { vaultPath, path, commitHash }, { path, commitHash }), [vaultPath]) const loadDiff = useCallback((path: string): Promise => tauriCall('get_file_diff', { vaultPath, path }, { path }), [vaultPath]) const isFileModified = useCallback((path: string): boolean => modifiedFiles.some((f) => f.path === path), [modifiedFiles]) const commitAndPush = useCallback((message: string): Promise => commitWithPush(vaultPath, message), [vaultPath]) return { entries, allContent, modifiedFiles, addEntry, updateEntry, replaceEntry, updateContent, loadModifiedFiles, loadGitHistory, loadDiff, loadDiffAtCommit, isFileModified, commitAndPush, } }