/**
 * Store Module
 * Single source of truth for all application state
 * Manages files, folders, sorting, filtering
 */
(function() {
    'use strict';

    // State
    const state = {
        // Directory structure
        rootHandle: null,
        folderTree: [],
        selectedFolders: new Set(),
        
        // Files
        allFiles: [],           // All files from selected folders
        displayFiles: [],       // After sorting and filtering
        
        // Sort state
        sortColumns: [],        // [{column: 'original', direction: 'asc'}]
        
        // Filter state
        filters: {},            // {columnName: AST (from zddc.filter.parse)}
        
        // UI state
        hideCompliant: false,
        calculateSha256: false
    };

    // Listeners for state changes
    const listeners = {
        'files': [],
        'folders': [],
        'sort': [],
        'filter': []
    };

    /**
     * Set sort columns
     */
    function on(event, callback) {
        if (listeners[event]) {
            listeners[event].push(callback);
        }
    }

    /**
     * Notify listeners of state change
     */
    function notify(event) {
        if (listeners[event]) {
            listeners[event].forEach(cb => cb());
        }
    }

    /**
     * Set root directory handle
     */
    function setRootHandle(handle) {
        state.rootHandle = handle;
    }

    /**
     * Set folder tree
     */
    function setFolderTree(tree) {
        state.folderTree = tree;
        notify('folders');
    }

    /**
     * Select/deselect folder
     */
    function toggleFolder(folderPath) {
        if (state.selectedFolders.has(folderPath)) {
            state.selectedFolders.delete(folderPath);
        } else {
            state.selectedFolders.add(folderPath);
        }
        loadFilesFromSelectedFolders();
    }

    /**
     * Select multiple folders
     */
    function setSelectedFolders(folderPaths) {
        state.selectedFolders.clear();
        folderPaths.forEach(path => state.selectedFolders.add(path));
        loadFilesFromSelectedFolders();
    }

    /**
     * Load files from selected folders
     */
    function loadFilesFromSelectedFolders() {
        state.allFiles = [];

        if (state.selectedFolders.size === 0) {
            updateDisplayFiles();
            return;
        }

        // Collect files from selected folders
        for (const folderPath of state.selectedFolders) {
            const folder = findFolderByPath(folderPath);
            if (folder && folder.files) {
                const files = folder.files.filter(f => !f.isDirectory);
                state.allFiles.push(...files);
            }
        }

        // Apply default sort if no sort set
        if (state.sortColumns.length === 0) {
            state.sortColumns = [{ column: 'original', direction: 'asc' }];
        }

        updateDisplayFiles();
    }

    /**
     * Find folder by path in tree
     */
    function findFolderByPath(path) {
        function search(folders) {
            for (const folder of folders) {
                if (folder.path === path) return folder;
                if (folder.children) {
                    const found = search(folder.children);
                    if (found) return found;
                }
            }
            return null;
        }
        return search(state.folderTree);
    }

    /**
     * Update display files (apply sort, filter, hide compliant)
     */
    function updateDisplayFiles() {
        let files = [...state.allFiles];

        // Apply filters
        files = applyFilters(files);

        // Apply hide compliant
        if (state.hideCompliant) {
            files = files.filter(file => {
                const newFilename = computeNewFilename(file);
                const validation = validateFilename(newFilename);
                return !validation.isValid;
            });
        }

        // Apply sort
        files = applySort(files);

        state.displayFiles = files;
        notify('files');
    }

    /**
     * Apply filters to files using zddc.filter ASTs
     */
    function applyFilters(files) {
        if (Object.keys(state.filters).length === 0) {
            return files;
        }

        return files.filter(file => {
            for (const [columnName, ast] of Object.entries(state.filters)) {
                const value = getColumnValue(file, columnName);
                if (!window.zddc.filter.matches(value, ast)) {
                    return false;
                }
            }
            return true;
        });
    }

    /**
     * Apply sort to files
     */
    function applySort(files) {
        if (state.sortColumns.length === 0) {
            return files;
        }

        return files.sort((a, b) => {
            for (const sort of state.sortColumns) {
                const result = compareValues(a, b, sort.column, sort.direction);
                if (result !== 0) return result;
            }
            return 0;
        });
    }

    /**
     * Compare two values for sorting
     */
    function compareValues(a, b, columnName, direction) {
        let aVal = getColumnValue(a, columnName);
        let bVal = getColumnValue(b, columnName);

        const comparison = String(aVal).localeCompare(String(bVal), undefined, {
            numeric: true,
            sensitivity: 'base'
        });

        return direction === 'asc' ? comparison : -comparison;
    }

    /**
     * Get column value from file (delegates to utils)
     */
    function getColumnValue(file, columnName) {
        return window.app.modules.utils.getColumnValue(file, columnName);
    }

    function computeNewFilename(file) {
        return window.app.modules.utils.computeNewFilename(file);
    }

    /**
     * Validate filename
     */
    function validateFilename(filename) {
        // Use existing validator module
        if (window.app.modules.validator) {
            return window.app.modules.validator.validateFilename(filename);
        }
        return { isValid: true, errors: [], warnings: [] };
    }

    /**
     * Match filter text against value
     */
    function matchesFilter(value, filterText) {
        // Simple contains for now - can enhance later
        return String(value).toLowerCase().includes(filterText.toLowerCase());
    }

    /**
     * Set sort columns
     */
    function setSortColumns(columns) {
        state.sortColumns = columns;
        updateDisplayFiles();
    }

    /**
     * Toggle sort on column
     */
    function toggleSort(columnName, multiSort) {
        if (!multiSort) {
            state.sortColumns = [];
        }

        const existingIndex = state.sortColumns.findIndex(s => s.column === columnName);

        if (existingIndex >= 0) {
            const current = state.sortColumns[existingIndex];
            if (current.direction === 'asc') {
                current.direction = 'desc';
            } else {
                state.sortColumns.splice(existingIndex, 1);
            }
        } else {
            state.sortColumns.push({ column: columnName, direction: 'asc' });
        }

        updateDisplayFiles();
        notify('sort');
    }

    /**
     * Set filter for column. ast is the pre-parsed zddc.filter AST.
     */
    function setFilter(columnName, filterText, ast) {
        if (filterText && ast && ast.length > 0) {
            state.filters[columnName] = ast;
        } else {
            delete state.filters[columnName];
        }
        updateDisplayFiles();
    }

    /**
     * Replace all filters at once. filtersObj is {columnName: rawString}.
     * Parses each value. Pass {} to clear all filters.
     */
    function setAllFilters(filtersObj) {
        state.filters = {};
        for (const [columnName, raw] of Object.entries(filtersObj)) {
            if (raw) {
                const ast = window.zddc.filter.parse(raw);
                if (ast && ast.length > 0) {
                    state.filters[columnName] = ast;
                }
            }
        }
        updateDisplayFiles();
    }

    /**
     * Set hide compliant flag
     */
    function setHideCompliant(hide) {
        state.hideCompliant = hide;
        updateDisplayFiles();
    }

    /**
     * Update file data
     */
    function updateFile(index, updates) {
        const file = state.displayFiles[index];
        if (!file) return;

        // Apply updates
        Object.assign(file, updates);
        
        // Mark as dirty unless explicitly set to false
        if (updates.isDirty !== false) {
            file.isDirty = true;
        }

        // Notify listeners (will trigger re-render)
        notify('files');
    }
    
    /**
     * Update file field (for editing)
     */
    function updateFileField(index, fieldName, value) {
        const file = state.displayFiles[index];
        if (!file) return;
        
        file[fieldName] = value;
        file.autoPopulated = false; // Clear auto-populated flag

        // Re-evaluate dirty: if every field still matches the parsed original,
        // and there is no manual filename override, the file is clean again.
        file.isDirty = _isFileDirty(file);
        
        // Notify listeners
        notify('files');
    }

    /**
     * A file is dirty if its computed filename differs from the original,
     * or if it has a manual filename override.
     */
    function _isFileDirty(file) {
        if (file.manualFilename) return true;
        const computed = zddc.formatFilename({
            trackingNumber: file.trackingNumber || '',
            revision:       file.revision || '',
            status:         file.status   || '',
            title:          file.title    || '',
            extension:      file.extension || '',
        });
        const original = zddc.joinExtension(file.originalFilename, file.extension);
        // If formatFilename returns '' (missing fields) fall back to original — not dirty
        return computed !== '' && computed !== original;
    }

    /**
     * Get display files (what should be shown in table)
     */
    function getDisplayFiles() {
        return state.displayFiles;
    }

    /**
     * Get all files (unfiltered)
     */
    function getAllFiles() {
        return state.allFiles;
    }

    /**
     * Get sort columns
     */
    function getSortColumns() {
        return state.sortColumns;
    }

    /**
     * Get selected folder count
     */
    function getSelectedFolderCount() {
        return state.selectedFolders.size;
    }

    /**
     * Get state (read-only)
     */
    function getState() {
        return {
            rootHandle: state.rootHandle,
            folderTree: state.folderTree,
            selectedFolders: Array.from(state.selectedFolders),
            allFiles: state.allFiles,
            displayFiles: state.displayFiles,
            sortColumns: state.sortColumns,
            filters: state.filters,
            hideCompliant: state.hideCompliant
        };
    }

    /**
     * Reset all state
     */
    function reset() {
        state.rootHandle = null;
        state.folderTree = [];
        state.selectedFolders.clear();
        state.allFiles = [];
        state.displayFiles = [];
        state.sortColumns = [];
        state.filters = {};
        state.hideCompliant = false;
        
        notify('files');
        notify('folders');
    }

    // Export
    window.app.modules.store = {
        on,
        notify,
        setRootHandle,
        setFolderTree,
        toggleFolder,
        setSelectedFolders,
        toggleSort,
        setFilter,
        setAllFilters,
        setHideCompliant,
        updateFile,
        updateFileField,
        getDisplayFiles,
        getAllFiles,
        getSortColumns,
        getSelectedFolderCount,
        getState,
        reset
    };
})();
