// Registry Firmware Component - CRUD interface for firmware registry
class FirmwareComponent extends Component {
    constructor(container, viewModel, eventBus) {
        super(container, viewModel, eventBus);
        
        logger.debug('FirmwareComponent: Constructor called');
        logger.debug('FirmwareComponent: Container:', container);
        
        // Initialize drawer component
        this.drawer = new DrawerComponent();
        
        // Registry connection status
        this.registryConnected = false;
        this.registryError = null;
    }

    setupEventListeners() {
        // Setup refresh button
        const refreshBtn = this.findElement('#refresh-firmware-btn');
        if (refreshBtn) {
            this.addEventListener(refreshBtn, 'click', this.refreshFirmwareList.bind(this));
        }

        // Setup add firmware button
        const addBtn = this.findElement('#add-firmware-btn');
        if (addBtn) {
            this.addEventListener(addBtn, 'click', this.showAddFirmwareForm.bind(this));
        }

        // Setup search input
        const searchInput = this.findElement('#firmware-search');
        if (searchInput) {
            this.addEventListener(searchInput, 'input', this.handleSearch.bind(this));
        }
    }

    setupViewModelListeners() {
        this.subscribeToProperty('firmwareList', this.renderFirmwareList.bind(this));
        this.subscribeToProperty('isLoading', this.updateLoadingState.bind(this));
        this.subscribeToProperty('searchQuery', this.updateSearchResults.bind(this));
        this.subscribeToProperty('registryConnected', this.updateRegistryStatus.bind(this));
    }

    mount() {
        super.mount();
        
        logger.debug('FirmwareComponent: Mounting...');
        
        // Check registry connection and load firmware list
        this.checkRegistryConnection();
        this.loadFirmwareList();
        
        logger.debug('FirmwareComponent: Mounted successfully');
    }

    unmount() {
        this.cleanupDynamicListeners();
        super.unmount();
    }

    async checkRegistryConnection() {
        try {
            await window.apiClient.getRegistryHealth();
            this.registryConnected = true;
            this.registryError = null;
            this.viewModel.set('registryConnected', true);
        } catch (error) {
            logger.error('Registry connection failed:', error);
            this.registryConnected = false;
            this.registryError = error.message;
            this.viewModel.set('registryConnected', false);
        }
    }

    async loadFirmwareList() {
        try {
            this.viewModel.set('isLoading', true);
            const firmwareList = await window.apiClient.listFirmwareFromRegistry();
            this.viewModel.set('firmwareList', firmwareList);
        } catch (error) {
            logger.error('Failed to load firmware list:', error);
            this.viewModel.set('firmwareList', []);
            this.showError('Failed to load firmware list: ' + error.message);
        } finally {
            this.viewModel.set('isLoading', false);
        }
    }

    async refreshFirmwareList() {
        await this.checkRegistryConnection();
        await this.loadFirmwareList();
    }

    renderFirmwareList() {
        const container = this.findElement('#firmware-list-container');
        if (!container) return;

        const groupedFirmware = this.viewModel.get('firmwareList') || [];
        const searchQuery = this.viewModel.get('searchQuery') || '';
        
        // Filter grouped firmware based on search query
        const filteredGroups = groupedFirmware.map(group => {
            if (!searchQuery) return group;
            
            // Split search query into individual terms
            const searchTerms = searchQuery.toLowerCase().split(/\s+/).filter(term => term.length > 0);
            
            // Filter firmware versions within the group
            const filteredFirmware = group.firmware.filter(firmware => {
                // All search terms must match somewhere in the firmware data
                return searchTerms.every(term => {
                    // Check group name
                    if (group.name.toLowerCase().includes(term)) {
                        return true;
                    }
                    
                    // Check version
                    if (firmware.version.toLowerCase().includes(term)) {
                        return true;
                    }
                    
                    // Check labels
                    if (Object.values(firmware.labels || {}).some(label => 
                        label.toLowerCase().includes(term)
                    )) {
                        return true;
                    }
                    
                    return false;
                });
            });
            
            // Return group with filtered firmware, or null if no firmware matches
            return filteredFirmware.length > 0 ? {
                ...group,
                firmware: filteredFirmware
            } : null;
        }).filter(group => group !== null);

        if (filteredGroups.length === 0) {
            container.innerHTML = `
                <div class="empty-state">
                    <div class="empty-icon">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="48" height="48">
                            <path d="M4 7l8-4 8 4v10l-8 4-8-4z"/>
                            <path d="M12 8v8"/>
                        </svg>
                    </div>
                    <div class="empty-title">${searchQuery ? 'No firmware found' : 'No firmware available'}</div>
                    <div class="empty-description">
                        ${searchQuery ? 'Try adjusting your search terms' : 'Upload your first firmware to get started'}
                    </div>
                </div>
            `;
            return;
        }
        
        // Auto-expand groups when search is active to show results
        const autoExpand = searchQuery.trim().length > 0;
        const firmwareHTML = filteredGroups.map(group => this.renderFirmwareGroup(group, autoExpand)).join('');
        
        container.innerHTML = `
            <div class="firmware-groups">
                ${firmwareHTML}
            </div>
        `;

        // Setup event listeners for firmware items
        this.setupFirmwareItemListeners();
    }

    renderFirmwareGroup(group, autoExpand = false) {
        const versionsHTML = group.firmware.map(firmware => this.renderFirmwareVersion(firmware)).join('');
        
        // Add 'expanded' class if autoExpand is true (e.g., when search results are shown)
        const expandedClass = autoExpand ? 'expanded' : '';
        
        return `
            <div class="firmware-group ${expandedClass}">
                <div class="firmware-group-header">
                    <div class="firmware-group-header-content">
                        <h3 class="firmware-group-name">${this.escapeHtml(group.name)}</h3>
                        <span class="firmware-group-count">${group.firmware.length} version${group.firmware.length !== 1 ? 's' : ''}</span>
                    </div>
                    <svg class="firmware-group-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="20" height="20">
                        <polyline points="6 9 12 15 18 9"/>
                    </svg>
                </div>
                <div class="firmware-versions">
                    ${versionsHTML}
                </div>
            </div>
        `;
    }

    renderFirmwareVersion(firmware) {
        const labels = firmware.labels || {};
        const labelsHTML = Object.entries(labels).map(([key, value]) => 
            `<span class="label-chip" title="${key}: ${value}">${key}: ${value}</span>`
        ).join('');

        const sizeKB = Math.round(firmware.size / 1024);
        
        return `
            <div class="firmware-version-item clickable" data-name="${firmware.name}" data-version="${firmware.version}" title="Click to edit firmware">
                <div class="firmware-version-main">
                    <div class="firmware-version-info">
                        <div class="firmware-version-number">v${this.escapeHtml(firmware.version)}</div>
                        <div class="firmware-size">${sizeKB} KB</div>
                    </div>
                    <div class="firmware-version-labels">
                        ${labelsHTML}
                    </div>
                </div>
                <div class="firmware-version-actions">
                    <button class="action-btn rollout-btn" title="Rollout firmware" data-name="${firmware.name}" data-version="${firmware.version}" data-labels='${JSON.stringify(firmware.labels)}'>
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                            <path d="M12 2L2 7l10 5 10-5-10-5z"/>
                            <path d="M2 17l10 5 10-5"/>
                            <path d="M2 12l10 5 10-5"/>
                        </svg>
                    </button>
                    <button class="action-btn download-btn" title="Download firmware" data-name="${firmware.name}" data-version="${firmware.version}">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                            <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
                            <polyline points="7,10 12,15 17,10"/>
                            <line x1="12" y1="15" x2="12" y2="3"/>
                        </svg>
                    </button>
                    <button class="action-btn delete-btn" title="Delete firmware" data-name="${firmware.name}" data-version="${firmware.version}">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                            <polyline points="3,6 5,6 21,6"/>
                            <path d="M19,6v14a2,2 0 0,1 -2,2H7a2,2 0 0,1 -2,-2V6m3,0V4a2,2 0 0,1 2,-2h4a2,2 0 0,1 2,2v2"/>
                            <line x1="10" y1="11" x2="10" y2="17"/>
                            <line x1="14" y1="11" x2="14" y2="17"/>
                        </svg>
                    </button>
                </div>
            </div>
        `;
    }

    renderFirmwareItem(firmware) {
        const labels = firmware.labels || {};
        const labelsHTML = Object.entries(labels).map(([key, value]) => 
            `<span class="label-chip" title="${key}: ${value}">${key}: ${value}</span>`
        ).join('');

        const sizeKB = Math.round(firmware.size / 1024);
        
        return `
            <div class="firmware-list-item" data-name="${firmware.name}" data-version="${firmware.version}">
                <div class="firmware-item-main">
                    <div class="firmware-item-info">
                        <div class="firmware-name">${this.escapeHtml(firmware.name)}</div>
                        <div class="firmware-version">v${this.escapeHtml(firmware.version)}</div>
                        <div class="firmware-size">${sizeKB} KB</div>
                    </div>
                    <div class="firmware-item-labels">
                        ${labelsHTML}
                    </div>
                </div>
                <div class="firmware-item-actions">
                    <button class="action-btn edit-btn" title="Edit firmware" data-name="${firmware.name}" data-version="${firmware.version}">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                            <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
                            <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
                        </svg>
                    </button>
                    <button class="action-btn download-btn" title="Download firmware" data-name="${firmware.name}" data-version="${firmware.version}">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                            <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
                            <polyline points="7,10 12,15 17,10"/>
                            <line x1="12" y1="15" x2="12" y2="3"/>
                        </svg>
                    </button>
                    <button class="action-btn delete-btn" title="Delete firmware" data-name="${firmware.name}" data-version="${firmware.version}">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                            <polyline points="3,6 5,6 21,6"/>
                            <path d="M19,6v14a2,2 0 0,1 -2,2H7a2,2 0 0,1 -2,-2V6m3,0V4a2,2 0 0,1 2,-2h4a2,2 0 0,1 2,2v2"/>
                            <line x1="10" y1="11" x2="10" y2="17"/>
                            <line x1="14" y1="11" x2="14" y2="17"/>
                        </svg>
                    </button>
                </div>
            </div>
        `;
    }

    setupFirmwareItemListeners() {
        // First, clean up existing listeners for dynamically created content
        this.cleanupDynamicListeners();
        this.dynamicUnsubscribers = [];
        
        // Firmware group header clicks (for expand/collapse)
        const groupHeaders = this.findAllElements('.firmware-group-header');
        groupHeaders.forEach(header => {
            const handler = (e) => {
                const group = header.closest('.firmware-group');
                group.classList.toggle('expanded');
            };
            header.addEventListener('click', handler);
            this.dynamicUnsubscribers.push(() => header.removeEventListener('click', handler));
        });

        // Version item clicks (for editing)
        const versionItems = this.findAllElements('.firmware-version-item.clickable');
        versionItems.forEach(item => {
            const handler = (e) => {
                // Don't trigger if clicking on action buttons
                if (e.target.closest('.firmware-version-actions')) {
                    return;
                }
                
                const name = item.getAttribute('data-name');
                const version = item.getAttribute('data-version');
                this.showEditFirmwareForm(name, version);
            };
            item.addEventListener('click', handler);
            this.dynamicUnsubscribers.push(() => item.removeEventListener('click', handler));
        });

        // Rollout buttons
        const rolloutBtns = this.findAllElements('.rollout-btn');
        rolloutBtns.forEach(btn => {
            const handler = (e) => {
                e.stopPropagation();
                const name = btn.getAttribute('data-name');
                const version = btn.getAttribute('data-version');
                const labels = JSON.parse(btn.getAttribute('data-labels') || '{}');
                this.showRolloutPanel(name, version, labels);
            };
            btn.addEventListener('click', handler);
            this.dynamicUnsubscribers.push(() => btn.removeEventListener('click', handler));
        });

        // Download buttons
        const downloadBtns = this.findAllElements('.download-btn');
        downloadBtns.forEach(btn => {
            const handler = (e) => {
                e.stopPropagation();
                const name = btn.getAttribute('data-name');
                const version = btn.getAttribute('data-version');
                this.downloadFirmware(name, version);
            };
            btn.addEventListener('click', handler);
            this.dynamicUnsubscribers.push(() => btn.removeEventListener('click', handler));
        });

        // Delete buttons
        const deleteBtns = this.findAllElements('.delete-btn');
        logger.debug('Found delete buttons:', deleteBtns.length);
        deleteBtns.forEach(btn => {
            const handler = (e) => {
                e.stopPropagation();
                const name = btn.getAttribute('data-name');
                const version = btn.getAttribute('data-version');
                logger.debug('Delete button clicked:', name, version);
                this.showDeleteConfirmation(name, version);
            };
            btn.addEventListener('click', handler);
            this.dynamicUnsubscribers.push(() => btn.removeEventListener('click', handler));
        });
    }

    cleanupDynamicListeners() {
        if (this.dynamicUnsubscribers) {
            this.dynamicUnsubscribers.forEach(unsub => unsub());
            this.dynamicUnsubscribers = [];
        }
    }

    showAddFirmwareForm() {
        this.openFirmwareForm('Add Firmware', null, null);
    }

    showEditFirmwareForm(name, version) {
        const groupedFirmware = this.viewModel.get('firmwareList') || [];
        
        // Find the firmware in the grouped data
        let firmware = null;
        for (const group of groupedFirmware) {
            if (group.name === name) {
                firmware = group.firmware.find(f => f.version === version);
                if (firmware) break;
            }
        }
        
        if (firmware) {
            this.openFirmwareForm('Edit Firmware', firmware, null);
        }
    }

    openFirmwareForm(title, firmwareData, onCloseCallback) {
        this.drawer.openDrawer(title, (contentContainer, setActiveComponent) => {
            const formComponent = new FirmwareFormComponent(contentContainer, this.viewModel, this.eventBus);
            setActiveComponent(formComponent);
            
            formComponent.setFirmwareData(firmwareData);
            formComponent.setOnSaveCallback(() => {
                this.loadFirmwareList();
                this.drawer.closeDrawer();
            });
            formComponent.setOnCancelCallback(() => {
                this.drawer.closeDrawer();
            });
            
            formComponent.mount();
        }, null, onCloseCallback, true); // Hide terminal button
    }

    async downloadFirmware(name, version) {
        try {
            const blob = await window.apiClient.downloadFirmwareFromRegistry(name, version);
            
            // Create download link
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `${name}-${version}.bin`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);
            
            this.showSuccess(`Firmware ${name} v${version} downloaded successfully`);
        } catch (error) {
            logger.error('Download failed:', error);
            this.showError('Download failed: ' + error.message);
        }
    }

    showDeleteConfirmation(name, version) {
        OverlayDialogComponent.danger({
            title: 'Delete Firmware',
            message: `Are you sure you want to delete firmware "${name}" version "${version}"?<br><br>This action cannot be undone.`,
            confirmText: 'Delete',
            cancelText: 'Cancel',
            onConfirm: () => this.deleteFirmware(name, version)
        });
    }

    async showRolloutPanel(name, version, labels) {
        try {
            // Get cluster node versions to show which nodes will be affected
            const nodeVersions = await window.apiClient.getClusterNodeVersions();
            
            // Filter nodes that match the firmware labels
            const matchingNodes = nodeVersions.nodes.filter(node => {
                return this.nodeMatchesLabels(node.labels, labels);
            });

            this.openRolloutDrawer(name, version, labels, matchingNodes);
        } catch (error) {
            logger.error('Failed to get cluster node versions:', error);
            this.showError('Failed to get cluster information: ' + error.message);
        }
    }

    nodeMatchesLabels(nodeLabels, firmwareLabels) {
        for (const [key, value] of Object.entries(firmwareLabels)) {
            if (!nodeLabels[key] || nodeLabels[key] !== value) {
                return false;
            }
        }
        return true;
    }

    openRolloutDrawer(name, version, labels, matchingNodes) {
        this.drawer.openDrawer('Rollout Firmware', (contentContainer, setActiveComponent) => {
            const rolloutComponent = new RolloutComponent(contentContainer, this.viewModel, this.eventBus);
            setActiveComponent(rolloutComponent);
            
            rolloutComponent.setRolloutData(name, version, labels, matchingNodes);
            rolloutComponent.setOnRolloutCallback((rolloutData) => {
                this.startRollout(rolloutData);
            });
            rolloutComponent.setOnCancelCallback(() => {
                this.drawer.closeDrawer();
            });
            
            // Store reference for status updates
            this.currentRolloutComponent = rolloutComponent;
            
            rolloutComponent.mount();
        }, null, null, true); // Hide terminal button
    }

    async startRollout(rolloutData) {
        try {
            // Start rollout in the panel (no backdrop)
            if (this.currentRolloutComponent) {
                this.currentRolloutComponent.startRollout();
            }
            
            const response = await window.apiClient.startRollout(rolloutData);
            
            logger.info('Rollout started:', response);
            this.showSuccess(`Rollout started for ${response.totalNodes} nodes`);
            
            // Set up WebSocket listener for rollout progress
            this.setupRolloutProgressListener(response.rolloutId);
            
        } catch (error) {
            logger.error('Rollout failed:', error);
            this.showError('Rollout failed: ' + error.message);
            
            // Reset rollout state on error
            if (this.currentRolloutComponent) {
                this.currentRolloutComponent.resetRolloutState();
            }
        }
    }

    showRolloutProgress() {
        // Create backdrop and progress overlay
        const backdrop = document.createElement('div');
        backdrop.className = 'rollout-backdrop';
        backdrop.id = 'rollout-backdrop';
        
        const progressOverlay = document.createElement('div');
        progressOverlay.className = 'rollout-progress-overlay';
        progressOverlay.innerHTML = `
            <div class="rollout-progress-content">
                <div class="rollout-progress-header">
                    <h3>Rolling Out Firmware</h3>
                </div>
                <div class="rollout-progress-body">
                    <div class="rollout-progress-info">
                        <p>Firmware rollout in progress...</p>
                        <p class="rollout-progress-text">Preparing rollout...</p>
                    </div>
                    <div class="rollout-progress-bar">
                        <div class="rollout-progress-fill" id="rollout-progress-fill"></div>
                    </div>
                    <div class="rollout-progress-details" id="rollout-progress-details">
                        <div class="rollout-node-list" id="rollout-node-list"></div>
                    </div>
                </div>
            </div>
        `;
        
        backdrop.appendChild(progressOverlay);
        document.body.appendChild(backdrop);
        
        // Block UI interactions
        document.body.style.overflow = 'hidden';
    }

    hideRolloutProgress() {
        const backdrop = document.getElementById('rollout-backdrop');
        if (backdrop) {
            document.body.removeChild(backdrop);
        }
        document.body.style.overflow = '';
    }

    setupRolloutProgressListener(rolloutId) {
        // Track completed nodes for parallel processing
        this.completedNodes = new Set();
        this.totalNodes = 0;
        
        const progressListener = (data) => {
            if (data.rolloutId === rolloutId) {
                // Set total nodes from first update
                if (this.totalNodes === 0) {
                    this.totalNodes = data.total;
                }
                this.updateRolloutProgress(data);
            }
        };
        
        window.wsClient.on('rolloutProgress', progressListener);
        
        // Store listener for cleanup
        this.currentRolloutListener = progressListener;
    }

    updateRolloutProgress(data) {
        // Update status in the rollout panel
        if (this.currentRolloutComponent) {
            this.currentRolloutComponent.updateNodeStatus(data.nodeIp, data.status);
        }
        
        // Track completed nodes for parallel processing
        if (data.status === 'completed') {
            this.completedNodes.add(data.nodeIp);
        } else if (data.status === 'failed') {
            // Also count failed nodes as "processed" for completion check
            this.completedNodes.add(data.nodeIp);
        }
        
        // Check if rollout is complete (all nodes processed)
        if (this.completedNodes.size >= this.totalNodes) {
            setTimeout(() => {
                this.showSuccess('Rollout completed successfully');
                
                // Clean up WebSocket listener
                if (this.currentRolloutListener) {
                    window.wsClient.off('rolloutProgress', this.currentRolloutListener);
                    this.currentRolloutListener = null;
                }
            }, 2000);
        }
    }

    async deleteFirmware(name, version) {
        try {
            await window.apiClient.deleteFirmwareFromRegistry(name, version);
            this.showSuccess(`Firmware ${name} v${version} deleted successfully`);
            await this.loadFirmwareList();
        } catch (error) {
            logger.error('Delete failed:', error);
            this.showError('Delete failed: ' + error.message);
        }
    }

    handleSearch(event) {
        const query = event.target.value;
        this.viewModel.set('searchQuery', query);
    }

    updateSearchResults() {
        // This method is called when searchQuery property changes
        // The actual filtering is handled in renderFirmwareList
        this.renderFirmwareList();
    }

    updateLoadingState() {
        const isLoading = this.viewModel.get('isLoading');
        const container = this.findElement('#firmware-list-container');
        
        if (isLoading && container) {
            container.innerHTML = `
                <div class="loading-state">
                    <div class="loading-spinner"></div>
                    <div class="loading-text">Loading firmware...</div>
                </div>
            `;
        }
    }

    updateRegistryStatus() {
        const isConnected = this.viewModel.get('registryConnected');
        const statusElement = this.findElement('#registry-status');
        
            if (statusElement) {
            if (isConnected) {
                statusElement.innerHTML = `
                    <span class="status-indicator connected">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="12" height="12">
                            <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
                            <polyline points="22,4 12,14.01 9,11.01"/>
                        </svg>
                        Registry Connected
                    </span>
                `;
            } else {
                statusElement.innerHTML = `
                    <span class="status-indicator disconnected">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="12" height="12">
                            <circle cx="12" cy="12" r="10"/>
                            <line x1="15" y1="9" x2="9" y2="15"/>
                            <line x1="9" y1="9" x2="15" y2="15"/>
                        </svg>
                        Registry Disconnected
                    </span>
                `;
            }
        }
    }


    showSuccess(message) {
        this.showNotification(message, 'success');
    }

    showError(message) {
        this.showNotification(message, 'error');
    }

    showNotification(message, type = 'info') {
        const notification = document.createElement('div');
        notification.className = `notification notification-${type}`;
        notification.textContent = message;
        
        document.body.appendChild(notification);
        
        setTimeout(() => {
            notification.classList.add('show');
        }, 100);
        
        setTimeout(() => {
            notification.classList.remove('show');
            setTimeout(() => {
                if (notification.parentNode) {
                    document.body.removeChild(notification);
                }
            }, 300);
        }, 3000);
    }

    escapeHtml(text) {
        if (typeof text !== 'string') return text;
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }
}

window.FirmwareComponent = FirmwareComponent; 