(function() {
    'use strict';
    // SHA-256 hashing and cache management

    const HASH_CACHE_FILENAME = '.hashes.json';

    // Calculate SHA-256 hash for a file (delegates to shared/hash.js)
    async function calculateFileHash(file) {
        return zddc.crypto.sha256File(file);
    }

    // Load hash cache for a directory
    async function loadHashCache(dirHandle) {
        try {
            const cacheHandle = await dirHandle.getFileHandle(HASH_CACHE_FILENAME);
            const cacheFile = await cacheHandle.getFile();
            const cacheText = await cacheFile.text();
            return JSON.parse(cacheText);
        } catch (err) {
            // Cache doesn't exist or can't be read
            return {};
        }
    }

    // Save hash cache for a directory
    async function saveHashCache(dirHandle, cache) {
        try {
            const cacheHandle = await dirHandle.getFileHandle(HASH_CACHE_FILENAME, { create: true });
            const writable = await cacheHandle.createWritable();
            await writable.write(JSON.stringify(cache, null, 2));
            await writable.close();
            return true;
        } catch (err) {
            console.warn('Unable to save hash cache:', err);
            return false;
        }
    }

    // Hash files in a directory with caching
    async function hashDirectoryFiles(dirHandle, files) {
        const cache = await loadHashCache(dirHandle);
        const updatedCache = {};
        const results = {};
    
        for (const fileInfo of files) {
            try {
                const file = await fileInfo.handle.getFile();
                const cacheKey = file.name;
                const lastModified = file.lastModified;
            
                // Check if we have a cached hash
                if (cache[cacheKey] && cache[cacheKey].lastModified === lastModified) {
                    // Use cached hash
                    results[fileInfo.id] = cache[cacheKey].hash;
                    updatedCache[cacheKey] = cache[cacheKey];
                } else {
                    // Calculate new hash
                    const hash = await calculateFileHash(file);
                    results[fileInfo.id] = hash;
                    updatedCache[cacheKey] = {
                        hash: hash,
                        lastModified: lastModified,
                        size: file.size
                    };
                }
            } catch (err) {
                console.error(`Error hashing file ${fileInfo.name}:`, err);
            }
        }
    
        // Try to save updated cache
        await saveHashCache(dirHandle, updatedCache);
    
        return results;
    }

    // Add hash information to files
    async function addHashesToFiles() {
        if (!window.app.files.length) return;
    
        // Hash operations require local file handles — not available in HTTP mode
        if (window.app.sourceMode === 'http') {
            console.log('Hash operations not available in HTTP mode.');
            return;
        }
    
        window.app.modules.export.showProgress('Calculating file hashes...', 0, window.app.files.length);
    
        try {
            // Group files by directory
            const filesByDir = {};
            window.app.files.forEach(file => {
                const dirPath = file.folderPath;
                if (!filesByDir[dirPath]) {
                    filesByDir[dirPath] = {
                        handle: null,
                        files: []
                    };
                }
                filesByDir[dirPath].files.push(file);
            });
        
            // Find directory handles
            for (const dirPath in filesByDir) {
                const folder = window.app.transmittalFolders.find(f => f.path === dirPath);
                if (folder) {
                    filesByDir[dirPath].handle = folder.handle;
                }
            }
        
            // Hash files in each directory
            let processed = 0;
            for (const dirPath in filesByDir) {
                const dirInfo = filesByDir[dirPath];
                if (dirInfo.handle) {
                    const hashes = await hashDirectoryFiles(dirInfo.handle, dirInfo.files);
                
                    // Update file objects with hashes
                    dirInfo.files.forEach(file => {
                        if (hashes[file.id]) {
                            file.hash = hashes[file.id];
                        }
                    });
                }
            
                processed += dirInfo.files.length;
                window.app.modules.export.showProgress('Calculating file hashes...', processed, window.app.files.length);
            }
        
            window.app.modules.export.hideProgress();
        
        } catch (err) {
            window.app.modules.export.hideProgress();
            console.error('Error calculating hashes:', err);
        }
    }

    // Verify file integrity
    async function verifyFileIntegrity(fileId) {
        const file = window.app.files.find(f => f.id === fileId);
        if (!file || !file.hash) {
            alert('No hash available for this file.');
            return;
        }
    
        if (!file.handle) {
            alert('File integrity verification is not available in HTTP mode.');
            return;
        }
    
        try {
            const fileData = await file.handle.getFile();
            const currentHash = await calculateFileHash(fileData);
        
            if (currentHash === file.hash) {
                alert('File integrity verified. Hash matches.');
            } else {
                alert('WARNING: File has been modified! Hash does not match.');
            }
        } catch (err) {
            alert('Error verifying file: ' + err.message);
        }
    }

    // Export hash report
    function exportHashReport() {
        const headers = ['File Path', 'SHA-256 Hash', 'Size', 'Last Modified'];
        const rows = [headers];
    
        window.app.filteredFiles.forEach(file => {
            if (file.hash) {
                rows.push([
                    file.path,
                    file.hash,
                    window.app.modules.export.formatFileSize(file.size),
                    new Date(file.modified).toISOString()
                ]);
            }
        });
    
        window.app.modules.export.downloadFile(window.app.modules.export.rowsToCSV(rows), 'file-hashes.csv', 'text/csv');
    }

    window.app.modules.hash = {
        calculateFileHash,
        loadHashCache,
        saveHashCache,
        hashDirectoryFiles,
        addHashesToFiles,
        verifyFileIntegrity,
        exportHashReport
    };

})();
