/**
 * @fileoverview Manages file operations and state for the room interface.
 * This file handles:
 * - File fetching and state management
 * - File operations (delete, rename, move, download)
 * - File selection and batch operations
 * - Star/unstar functionality
 * - Navigation and path management
 */

/**
 * @class FileManager
 * @classdesc Manages all file-related operations and state in the room interface.
 * Handles file operations, selection, and navigation.
 */
export class FileManager {
    /**
     * Creates a new FileManager instance.
     * @param {RoomManager} roomManager - The parent RoomManager instance
     */
    constructor(roomManager) {
        console.log('[FileManager] Initializing...');
        this.roomManager = roomManager;
        this.currentFiles = [];
        this.selectedItems = new Set();
        this.lastSelectedIndex = -1;
        this.batchDeleteItems = null;
        this.fileToDelete = null;
        this.fileToDeletePath = '';
        this.fileToMove = null;
        this.fileToMovePath = '';
        this.fileToRename = null;
        this.fileToRenamePath = '';
        console.log('[FileManager] Initialized with roomManager:', roomManager);
    }
    
    /**
     * Fetches files from the server for the current path.
     * @async
     * @returns {Promise<Array>} A promise that resolves with the array of files
     * @throws {Error} If the fetch operation fails
     */
    async fetchFiles() {
        console.log('[FileManager] Fetching files...');
        try {
            const url = `/api/rooms/${this.roomManager.roomId}/files${this.roomManager.currentPath ? `?path=${encodeURIComponent(this.roomManager.currentPath)}` : ''}`;
            console.log('[FileManager] Fetching from URL:', url);
            
            const response = await fetch(url);
            console.log('[FileManager] Response status:', response.status);
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const data = await response.json();
            console.log('[FileManager] Received data:', data);
            
            this.currentFiles = data.sort((a, b) => a.name.localeCompare(b.name));
            console.log('[FileManager] Sorted files:', this.currentFiles);
            
            // Update the view
            await this.roomManager.viewManager.renderFiles(this.currentFiles);
            console.log('[FileManager] Files rendered in view');
            
            return this.currentFiles;
        } catch (error) {
            console.error('[FileManager] Error fetching files:', error);
            document.getElementById('fileError').textContent = 'Failed to load files. Please try again.';
            throw error;
        }
    }
    
    /**
     * Deletes a file from the server.
     * @async
     * @param {string} filename - The name of the file to delete
     * @param {string} [path=''] - The path of the file to delete
     * @throws {Error} If the delete operation fails
     */
    async deleteFile(filename, path = '') {
        console.log('[FileManager] Deleting file:', { filename, path });
        const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
        
        try {
            let url = `/api/rooms/${this.roomManager.roomId}/files/${encodeURIComponent(filename)}`;
            if (path) {
                url += `?path=${encodeURIComponent(path)}`;
            }
            
            const response = await fetch(url, {
                method: 'DELETE',
                headers: {
                    'X-CSRF-Token': csrfToken
                }
            });
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const result = await response.json();
            if (result.success) {
                console.log('[FileManager] File deleted successfully');
                await this.fetchFiles();
                // Clear any existing error message
                const errorEl = document.getElementById('fileError');
                if (errorEl) {
                    errorEl.textContent = '';
                }
            } else {
                console.error('[FileManager] Failed to delete file:', result.error);
                const errorEl = document.getElementById('fileError');
                if (errorEl) {
                    errorEl.textContent = result.error || 'Failed to delete file.';
                }
            }
        } catch (error) {
            console.error('[FileManager] Error deleting file:', error);
            const errorEl = document.getElementById('fileError');
            if (errorEl) {
                errorEl.textContent = 'Failed to delete file. Please try again.';
            }
        }
    }
    
    /**
     * Renames a file on the server.
     * @async
     * @param {string} filename - The name of the file to rename
     * @param {string} newName - The new name for the file
     * @returns {Promise<Object>} A promise that resolves with the result of the rename operation
     * @throws {Error} If the rename operation fails
     */
    async renameFile(filename, newName) {
        console.log('[FileManager] Renaming file:', { filename, newName });
        
        // Check if the file has an extension
        const hasExtension = filename.includes('.');
        if (hasExtension) {
            const oldExt = filename.substring(filename.lastIndexOf('.'));
            const newExt = newName.includes('.') ? newName.substring(newName.lastIndexOf('.')) : '';
            
            // If the new name doesn't have the same extension, append the old extension
            if (newExt !== oldExt) {
                newName = newName + oldExt;
            }
        }
        
        try {
            const response = await fetch(`/api/rooms/${this.roomManager.roomId}/rename`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                },
                body: JSON.stringify({ 
                    old_name: filename,
                    new_name: newName,
                    path: this.fileToRenamePath
                })
            });
            console.log('[FileManager] Rename response status:', response.status);
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const result = await response.json();
            console.log('[FileManager] Rename result:', result);
            
            if (result.success) {
                // Update the file's name in currentFiles
                const fileIndex = this.currentFiles.findIndex(file => file.name === filename && file.path === this.fileToRenamePath);
                if (fileIndex !== -1) {
                    this.currentFiles[fileIndex].name = newName;
                    await this.roomManager.viewManager.renderFiles(this.currentFiles);
                    console.log('[FileManager] File renamed and view updated');
                }
                // Clear the rename state
                this.fileToRename = null;
                this.fileToRenamePath = '';
                return { success: true, message: 'File renamed successfully' };
            } else {
                throw new Error(result.message || 'Failed to rename file');
            }
        } catch (error) {
            console.error('[FileManager] Error renaming file:', error);
            return { success: false, message: error.message };
        }
    }
    
    /**
     * Moves a file to a new location.
     * @async
     * @param {string} fileId - The ID of the file to move
     * @param {string} targetPath - The target path to move the file to
     * @returns {Promise<Object>} A promise that resolves with the result of the move operation
     * @throws {Error} If the move operation fails
     */
    async moveFile(fileId, targetPath) {
        console.log('[FileManager] Starting moveFile...');
        console.log('[FileManager] Parameters:', { fileId, targetPath });
        
        try {
            const file = this.currentFiles.find(f => f.id === fileId);
            console.log('[FileManager] Found file to move:', file);

            if (!file) {
                console.error('[FileManager] File not found with ID:', fileId);
                throw new Error('File not found');
            }

            console.log('[FileManager] Sending move request...');
            const response = await fetch(`/api/rooms/${this.roomManager.roomId}/move`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                },
                body: JSON.stringify({
                    filename: file.name,
                    source_path: file.path || '',
                    target_path: targetPath
                })
            });
            
            console.log('[FileManager] Move response status:', response.status);
            const result = await response.json();
            console.log('[FileManager] Move response data:', result);
            
            if (result.success) {
                console.log('[FileManager] Move successful, updating view...');
                this.currentFiles = this.currentFiles.filter(f => f.id !== fileId);
                await this.roomManager.viewManager.renderFiles(this.currentFiles);
                console.log('[FileManager] View updated after move');
                return { success: true, message: 'File moved successfully' };
            } else {
                console.error('[FileManager] Move failed:', result.message);
                throw new Error(result.message || 'Failed to move file');
            }
        } catch (error) {
            console.error('[FileManager] Error in moveFile:', error);
            console.error('[FileManager] Error details:', {
                message: error.message,
                stack: error.stack
            });
            return { success: false, message: error.message };
        }
    }

    /**
     * Handles the confirmed move operation after user confirmation.
     * @async
     * @throws {Error} If the move operation fails
     */
    async moveFileConfirmed() {
        console.log('[FileManager] Starting moveFileConfirmed...');
        console.log('[FileManager] Current state:', {
            fileToMove: this.fileToMove,
            fileToMovePath: this.fileToMovePath,
            currentFiles: this.currentFiles
        });

        if (!this.fileToMove) {
            console.error('[FileManager] No file selected for move operation');
            document.getElementById('moveError').textContent = 'No file selected for move.';
            return;
        }

        const targetPath = document.getElementById('moveTargetFolder').value;
        console.log('[FileManager] Selected target path:', targetPath);

        const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
        console.log('[FileManager] CSRF Token:', csrfToken ? 'Present' : 'Missing');

        // Get the file from currentFiles using the filename
        console.log('[FileManager] Attempting to find file with name:', this.fileToMove);
        const file = this.currentFiles.find(f => f.name === this.fileToMove);
        console.log('[FileManager] Found file:', file);

        if (!file) {
            console.error('[FileManager] File not found in currentFiles. Available files:', this.currentFiles);
            document.getElementById('moveError').textContent = 'File not found.';
            return;
        }

        console.log('[FileManager] Preparing move request with data:', {
            filename: file.name,
            source_path: this.fileToMovePath,
            target_path: targetPath
        });
        
        try {
            const url = `/api/rooms/${this.roomManager.roomId}/move`;
            console.log('[FileManager] Sending request to:', url);
            
            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-Token': csrfToken
                },
                body: JSON.stringify({
                    filename: file.name,
                    source_path: this.fileToMovePath,
                    target_path: targetPath
                })
            });
            
            console.log('[FileManager] Response status:', response.status);
            const result = await response.json();
            console.log('[FileManager] Response data:', result);

            if (result.success) {
                console.log('[FileManager] Move successful, refreshing files...');
                await this.fetchFiles();
                this.fileToMove = null;
                this.fileToMovePath = '';
                this.roomManager.modalManager.moveModal.hide();
                document.getElementById('moveError').textContent = '';
                console.log('[FileManager] Move operation completed successfully');
            } else {
                console.error('[FileManager] Move failed:', result.error);
                document.getElementById('moveError').textContent = result.error || 'Move failed.';
            }
        } catch (error) {
            console.error('[FileManager] Error during move operation:', error);
            console.error('[FileManager] Error details:', {
                message: error.message,
                stack: error.stack
            });
            document.getElementById('moveError').textContent = 'Move failed.';
        }
    }
    
    /**
     * Toggles the star status of a file.
     * @async
     * @param {string} filename - The name of the file to toggle star for
     * @param {string} path - The path of the file
     * @throws {Error} If the star toggle operation fails
     */
    async toggleStar(filename, path) {
        console.log('[FileManager] Toggling star for:', filename, 'path:', path);
        const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
        
        // Find and update the button immediately for better UX
        const starButton = event.target.closest('.file-action-btn');
        if (starButton) {
            // Get the current state from the button's title
            const isStarred = starButton.title === 'Unstar';
            
            // Update button appearance using CSS variables
            starButton.style.backgroundColor = isStarred ? 'var(--primary-opacity-8)' : 'var(--warning-opacity-15)';
            starButton.style.color = isStarred ? 'var(--primary-color)' : 'var(--warning-color)';
            starButton.title = isStarred ? 'Star' : 'Unstar';
        }
        
        try {
            const response = await fetch(`/api/rooms/${this.roomManager.roomId}/star`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-Token': csrfToken
                },
                body: JSON.stringify({
                    filename: filename,
                    path: path || ''
                })
            });
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const data = await response.json();
            console.log('[FileManager] Star toggle response:', data);
            
            if (data.success) {
                // Update the file's starred status in currentFiles
                const fileIndex = this.currentFiles.findIndex(f => f.name === filename && f.path === path);
                if (fileIndex !== -1) {
                    this.currentFiles[fileIndex].starred = data.starred;
                }
            } else {
                // Revert the button if the server request failed
                if (starButton) {
                    const isStarred = starButton.title === 'Unstar';
                    starButton.style.backgroundColor = isStarred ? 'var(--primary-opacity-8)' : 'var(--warning-opacity-15)';
                    starButton.style.color = isStarred ? 'var(--primary-color)' : 'var(--warning-color)';
                    starButton.title = isStarred ? 'Star' : 'Unstar';
                }
                throw new Error(data.error || 'Failed to toggle star');
            }
        } catch (error) {
            // Revert the button if there was an error
            if (starButton) {
                const isStarred = starButton.title === 'Unstar';
                starButton.style.backgroundColor = isStarred ? 'var(--primary-opacity-8)' : 'var(--warning-opacity-15)';
                starButton.style.color = isStarred ? 'var(--primary-color)' : 'var(--warning-color)';
                starButton.title = isStarred ? 'Star' : 'Unstar';
            }
            console.error('[FileManager] Error toggling star:', error);
            throw error;
        }
    }
    
    /**
     * Downloads a single file.
     * @async
     * @param {string} filename - The name of the file to download
     * @param {string} [path=''] - The path of the file
     * @throws {Error} If the download operation fails
     */
    async downloadFile(filename, path = '') {
        console.log('[FileManager] Downloading file:', { filename, path });
        let url = `/api/rooms/${this.roomManager.roomId}/files/${encodeURIComponent(filename)}`;
        if (path) {
            url += `?path=${encodeURIComponent(path)}`;
        }
        console.log('[FileManager] Download URL:', url);
        
        try {
            const response = await fetch(url, {
                method: 'GET',
                headers: {
                    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                }
            });
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const blob = await response.blob();
            const downloadUrl = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = downloadUrl;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(downloadUrl);
            document.body.removeChild(a);
            console.log('[FileManager] Download initiated');
        } catch (error) {
            console.error('[FileManager] Error downloading file:', error);
            document.getElementById('fileError').textContent = 'Failed to download file. Please try again.';
            throw error;
        }
    }
    
    /**
     * Downloads multiple selected files as a zip archive.
     * @async
     * @throws {Error} If the download operation fails
     */
    async downloadSelected() {
        console.log('[FileManager] Downloading selected files...');
        const selectedItems = this.getSelectedItems();
        console.log('[FileManager] Selected items:', selectedItems);
        
        if (selectedItems.length === 0) {
            console.log('[FileManager] No files selected for download');
            return;
        }

        // Filter out folders and get only file IDs
        const fileIds = selectedItems
            .filter(item => item.type !== 'folder')
            .map(item => item.id);

        if (fileIds.length === 0) {
            console.log('[FileManager] No files to download (only folders selected)');
            return;
        }

        try {
            const response = await fetch(`/api/rooms/${this.roomManager.roomId}/download-zip`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                },
                body: JSON.stringify({ items: selectedItems })
            });
            console.log('[FileManager] Download response status:', response.status);
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const blob = await response.blob();
            console.log('[FileManager] Received blob:', blob);
            
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'files.zip';
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
            document.body.removeChild(a);
            console.log('[FileManager] Download initiated');
        } catch (error) {
            console.error('[FileManager] Error downloading files:', error);
            document.getElementById('fileError').textContent = 'Failed to download files. Please try again.';
            throw error;
        }
    }

    /**
     * Handles the confirmed delete operation after user confirmation.
     * Supports both single file and batch deletion.
     * @async
     * @throws {Error} If the delete operation fails
     */
    async deleteFileConfirmed() {
        const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
        if (this.batchDeleteItems && this.batchDeleteItems.length) {
            // Batch delete
            let completed = 0;
            const deleteNext = async () => {
                if (completed >= this.batchDeleteItems.length) {
                    await this.fetchFiles();
                    this.batchDeleteItems = null;
                    this.fileToDelete = null;
                    this.fileToDeletePath = '';
                    this.roomManager.modalManager.deleteModal.hide();
                    document.getElementById('fileError').textContent = '';
                    return;
                }
                const item = this.batchDeleteItems[completed];
                let url = `/api/rooms/${this.roomManager.roomId}/files/${encodeURIComponent(item.name)}`;
                if (item.path) url += `?path=${encodeURIComponent(item.path)}`;
                try {
                    const response = await fetch(url, {
                        method: 'DELETE',
                        headers: { 'X-CSRF-Token': csrfToken }
                    });
                    const result = await response.json();
                    if (!result.success) {
                        throw new Error(result.error || 'Delete failed');
                    }
                } catch (error) {
                    console.error('[FileManager] Error deleting file:', error);
                }
                completed++;
                await deleteNext();
            };
            await deleteNext();
            return;
        }
        
        if (!this.fileToDelete) return;
        let url = `/api/rooms/${this.roomManager.roomId}/files/${encodeURIComponent(this.fileToDelete)}`;
        if (this.fileToDeletePath) url += `?path=${encodeURIComponent(this.fileToDeletePath)}`;
        
        try {
            const response = await fetch(url, {
                method: 'DELETE',
                headers: { 'X-CSRF-Token': csrfToken }
            });
            const result = await response.json();
            if (result.success) {
                await this.fetchFiles();
                this.fileToDelete = null;
                this.fileToDeletePath = '';
                this.roomManager.modalManager.deleteModal.hide();
                document.getElementById('fileError').textContent = '';
            } else {
                document.getElementById('fileError').textContent = result.error || 'Delete failed.';
            }
        } catch (error) {
            console.error('[FileManager] Error deleting file:', error);
            document.getElementById('fileError').textContent = 'Delete failed.';
        }
    }
    
    /**
     * Updates the file selection based on user interaction.
     * Supports single selection, CTRL+click for multiple selection, and SHIFT+click for range selection.
     * @param {number} index - The index of the file being selected
     * @param {Event} event - The click event that triggered the selection
     */
    updateSelection(index, event) {
        console.log('[FileManager] Updating selection:', { index, event });
        
        // Prevent selection if clicking on a checkbox or action button
        if (event.target.classList.contains('select-item-checkbox') || event.target.closest('.file-action-btn')) {
            return;
        }

        const checkboxes = document.querySelectorAll('.select-item-checkbox');
        const checkbox = checkboxes[index];
        if (!checkbox) return;

        if (event.ctrlKey) {
            // CTRL + Click: Toggle individual selection
            checkbox.checked = !checkbox.checked;
            if (checkbox.checked) {
                this.selectedItems.add(index);
            } else {
                this.selectedItems.delete(index);
            }
        } else if (event.shiftKey && this.lastSelectedIndex !== -1) {
            // SHIFT + Click: Select range
            const start = Math.min(this.lastSelectedIndex, index);
            const end = Math.max(this.lastSelectedIndex, index);
            for (let i = start; i <= end; i++) {
                checkboxes[i].checked = true;
                this.selectedItems.add(i);
            }
        } else {
            // Normal click: Select single item
            const wasChecked = checkbox.checked;
            checkboxes.forEach(cb => {
                cb.checked = false;
                this.selectedItems.delete(parseInt(cb.dataset.index));
            });
            checkbox.checked = !wasChecked;
            if (!wasChecked) {
                this.selectedItems.add(index);
            }
        }

        this.lastSelectedIndex = index;
        this.roomManager.viewManager.updateMultiSelectUI();
    }
    
    /**
     * Gets an array of currently selected file objects.
     * @returns {Array<Object>} Array of selected file objects
     */
    getSelectedItems() {
        console.log('[FileManager] Getting selected items');
        return Array.from(this.selectedItems).map(index => this.currentFiles[index]);
    }
    
    /**
     * Clears all file selections and updates the UI.
     */
    clearSelection() {
        console.log('[FileManager] Clearing selection');
        this.selectedItems.clear();
        this.lastSelectedIndex = -1;
        const checkboxes = document.querySelectorAll('.select-item-checkbox');
        checkboxes.forEach(cb => cb.checked = false);
        this.roomManager.viewManager.updateMultiSelectUI();
    }
    
    /**
     * Navigates to the parent folder of the current path.
     */
    navigateToParent() {
        if (!this.roomManager.currentPath) return;
        const parts = this.roomManager.currentPath.split('/');
        parts.pop(); // Remove the last part
        const parentPath = parts.join('/');
        this.roomManager.navigateTo(parentPath);
    }
} 