// Model Duplicates Manager Component for LoRAs and Checkpoints
import { showToast, showActionToast } from '../utils/uiHelpers.js';
import { handleUndoDelete } from '../utils/undoHelpers.js';
import { translate } from '../utils/i18nHelpers.js';
import { state, getCurrentPageState } from '../state/index.js';
import { formatDate } from '../utils/formatters.js';
import { resetAndReload} from '../api/modelApiFactory.js';
import { getShowDuplicatesNotification, setShowDuplicatesNotification } from '../utils/storageHelpers.js';

export class ModelDuplicatesManager {
    constructor(pageManager, modelType = 'loras') {
        this.pageManager = pageManager;
        this.duplicateGroups = [];
        this.inDuplicateMode = false;
        this.selectedForDeletion = new Set();
        this.modelType = modelType; // Use the provided modelType or default to 'loras'

        // Verification tracking
        this.verifiedGroups = new Set(); // Track which groups have been verified
        this.mismatchedFiles = new Map(); // Map file paths to actual hashes for mismatched files
        
        // Badge visibility preference
        this.showBadge = getShowDuplicatesNotification(); // Default to true (show badge)
        
        // Event handler references for cleanup
        this.badgeToggleHandler = null;
        this.helpTooltipHandlers = {
            mouseenter: null,
            mouseleave: null,
            click: null
        };
        
        // Bind methods
        this.renderModelCard = this.renderModelCard.bind(this);
        this.renderTooltip = this.renderTooltip.bind(this);
        this.checkDuplicatesCount = this.checkDuplicatesCount.bind(this);
        this.handleVerifyHashes = this.handleVerifyHashes.bind(this);
        
        // Keep track of which controls need to be re-enabled
        this.disabledControls = [];
        
        // Check for duplicates on load
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', this.checkDuplicatesCount);
        } else {
            this.checkDuplicatesCount();
        }
    }
    
    // Method to check for duplicates count using existing endpoint
    async checkDuplicatesCount() {
        try {
            const params = this._buildFilterQueryParams();
            const endpoint = `/api/lm/${this.modelType}/find-duplicates`;
            const url = params.toString() ? `${endpoint}?${params}` : endpoint;

            const response = await fetch(url);

            if (!response.ok) {
                throw new Error(`Failed to get duplicates count: ${response.statusText}`);
            }

            const data = await response.json();

            if (data.success) {
                const duplicatesCount = (data.duplicates || []).length;
                this.updateDuplicatesBadge(duplicatesCount);
            } else {
                this.updateDuplicatesBadge(0);
            }
        } catch (error) {
            console.error('Error checking duplicates count:', error);
            this.updateDuplicatesBadge(0);
        }
    }
    
    // Method to update the badge
    updateDuplicatesBadge(count) {
        const badge = document.getElementById('duplicatesBadge');
        if (!badge) return;
        
        // Check if badge should be hidden based on user preference
        if (!this.showBadge && !this.inDuplicateMode) {
            badge.style.display = 'none';
            badge.textContent = '';
            badge.classList.remove('pulse');
            return;
        }
        
        if (count > 0) {
            badge.style.display = 'inline-flex';
            badge.textContent = count;
            badge.classList.add('pulse');
        } else {
            badge.textContent = '';
            badge.classList.remove('pulse');
        }
    }
    
    // Toggle method to enter/exit duplicates mode
    toggleDuplicateMode() {
        if (this.inDuplicateMode) {
            this.exitDuplicateMode();
        } else {
            this.findDuplicates();
        }
    }
    
    async findDuplicates() {
        try {
            const params = this._buildFilterQueryParams();
            const endpoint = `/api/lm/${this.modelType}/find-duplicates`;
            const url = params.toString() ? `${endpoint}?${params}` : endpoint;

            const response = await fetch(url);
            if (!response.ok) {
                throw new Error(`Failed to find duplicates: ${response.statusText}`);
            }

            const data = await response.json();
            if (!data.success) {
                throw new Error(data.error || 'Unknown error finding duplicates');
            }

            this.duplicateGroups = data.duplicates || [];
            this._pruneVerificationState();

            // Update the badge with the current count
            this.updateDuplicatesBadge(this.duplicateGroups.length);

            if (this.duplicateGroups.length === 0) {
                showToast('toast.duplicates.noDuplicatesFound', { type: this.modelType }, 'info');
                // If already in duplicate mode, exit to clear the display
                if (this.inDuplicateMode) {
                    this.exitDuplicateMode();
                }
                return false;
            }

            this.enterDuplicateMode();
            return true;
        } catch (error) {
            console.error('Error finding duplicates:', error);
            showToast('toast.duplicates.findFailed', { message: error.message }, 'error');
            return false;
        }
    }

    /**
     * Build query parameters from current filter state for duplicate finding.
     * @returns {URLSearchParams} The query parameters to append to the API endpoint
     */
    _buildFilterQueryParams() {
        const params = new URLSearchParams();
        const pageState = getCurrentPageState();
        const filters = pageState?.filters;

        if (!filters) return params;

        // Base model filters
        if (filters.baseModel && Array.isArray(filters.baseModel)) {
            filters.baseModel.forEach(m => params.append('base_model', m));
        }

        // Tag filters (tri-state: include/exclude)
        if (filters.tags && typeof filters.tags === 'object') {
            Object.entries(filters.tags).forEach(([tag, state]) => {
                if (state === 'include') {
                    params.append('tag_include', tag);
                } else if (state === 'exclude') {
                    params.append('tag_exclude', tag);
                }
            });
        }

        // Model type filters
        if (filters.modelTypes && Array.isArray(filters.modelTypes)) {
            filters.modelTypes.forEach(t => params.append('model_type', t));
        }

        // Folder filter (from active folder state)
        if (pageState.activeFolder) {
            params.append('folder', pageState.activeFolder);
        }

        // Favorites filter
        if (pageState.showFavoritesOnly) {
            params.append('favorites_only', 'true');
        }

        return params;
    }
    
    enterDuplicateMode() {
        this.inDuplicateMode = true;
        this.selectedForDeletion.clear();
        
        // Update state
        const pageState = getCurrentPageState();
        pageState.duplicatesMode = true;
        
        // Show duplicates banner
        const banner = document.getElementById('duplicatesBanner');
        const countSpan = document.getElementById('duplicatesCount');
        
        if (banner && countSpan) {
            countSpan.textContent = `Found ${this.duplicateGroups.length} duplicate group${this.duplicateGroups.length !== 1 ? 's' : ''}`;
            banner.style.display = 'block';
            
            // Setup help tooltip behavior
            this.setupHelpTooltip();
            
            // Setup badge toggle control
            this.setupBadgeToggle();
        }
        
        // Disable virtual scrolling if active
        if (state.virtualScroller) {
            state.virtualScroller.disable();
        }
        
        // Add duplicate-mode class to the body
        document.body.classList.add('duplicate-mode');
        
        // Render duplicate groups
        this.renderDuplicateGroups();
        
        // Update selected count
        this.updateSelectedCount();
        
        // Update Duplicates button to show active state
        const duplicatesBtn = document.getElementById('findDuplicatesBtn');
        if (duplicatesBtn) {
            duplicatesBtn.classList.add('active');
            duplicatesBtn.title = 'Exit Duplicates Mode';
            // Change icon and text to indicate it's now an exit button
            duplicatesBtn.innerHTML = '<i class="fas fa-times"></i> Exit Duplicates';
        }
        
        // Disable all control buttons except the duplicates button
        this.disableControlButtons();
    }
    
    exitDuplicateMode() {
        this.inDuplicateMode = false;
        this.selectedForDeletion.clear();
        
        // Update state
        const pageState = getCurrentPageState();
        pageState.duplicatesMode = false;
        
        // Clean up event handlers before hiding banner
        this.cleanupEventHandlers();
        
        // Hide duplicates banner
        const banner = document.getElementById('duplicatesBanner');
        if (banner) {
            banner.style.display = 'none';
        }
        
        // Remove duplicate-mode class from the body
        document.body.classList.remove('duplicate-mode');
        
        // Clear the model grid first
        const modelGrid = document.getElementById('modelGrid');
        if (modelGrid) {
            modelGrid.innerHTML = '';
        }
        
        // Re-enable virtual scrolling
        state.virtualScroller.enable();
        
        // Restore Duplicates button to its original state
        const duplicatesBtn = document.getElementById('findDuplicatesBtn');
        if (duplicatesBtn) {
            duplicatesBtn.classList.remove('active');
            duplicatesBtn.title = 'Find duplicate models';
            duplicatesBtn.innerHTML = '<i class="fas fa-clone"></i> Duplicates <span id="duplicatesBadge" class="badge"></span>';
            
            // Restore badge
            const newBadge = duplicatesBtn.querySelector('#duplicatesBadge');
            const oldBadge = document.getElementById('duplicatesBadge');
            if (oldBadge && oldBadge.textContent) {
                newBadge.textContent = oldBadge.textContent;
                newBadge.classList.add('pulse');
            }
        }
        
        // Re-enable all control buttons
        this.enableControlButtons();

        this.checkDuplicatesCount();
    }
    
    // Disable all control buttons except the duplicates button
    disableControlButtons() {
        this.disabledControls = [];
        
        // Select all control buttons except the duplicates button
        const controlButtons = document.querySelectorAll('.control-group button:not(#findDuplicatesBtn), .dropdown-group, .toggle-folders-btn, #favoriteFilterBtn');
        
        controlButtons.forEach(button => {
            // Only disable enabled buttons (don't disable already disabled buttons)
            if (!button.disabled && !button.classList.contains('disabled')) {
                this.disabledControls.push(button);
                button.disabled = true;
                button.classList.add('disabled-during-duplicates');
            }
        });
    }
    
    // Re-enable all previously disabled control buttons
    enableControlButtons() {
        this.disabledControls.forEach(button => {
            button.disabled = false;
            button.classList.remove('disabled-during-duplicates');
        });
        this.disabledControls = [];
    }
    
    renderDuplicateGroups() {
        const modelGrid = document.getElementById('modelGrid');
        if (!modelGrid) return;
        
        // Clear existing content
        modelGrid.innerHTML = '';
        
        // Render each duplicate group
        this.duplicateGroups.forEach((group, groupIndex) => {
            const groupDiv = document.createElement('div');
            groupDiv.className = 'duplicate-group';
            groupDiv.dataset.hash = group.hash;
            
            // Create group header
            const header = document.createElement('div');
            header.className = 'duplicate-group-header';
            
            // Create verification status badge
            const verificationBadge = document.createElement('span');
            verificationBadge.className = 'verification-badge';
            if (this.verifiedGroups.has(group.hash)) {
                verificationBadge.classList.add('verified');
                verificationBadge.innerHTML = '<i class="fas fa-check-circle"></i> Verified';
            } else {
                verificationBadge.classList.add('metadata');
                verificationBadge.innerHTML = '<i class="fas fa-tag"></i> Metadata Hash';
            }
            
            header.innerHTML = `
                <span>Duplicate Group #${groupIndex + 1} (${group.models.length} models with same hash: ${group.hash})</span>
                <span>
                    <button class="btn-verify-hashes" data-hash="${group.hash}" title="Recalculate SHA256 hashes to verify if these are true duplicates">
                        <i class="fas fa-fingerprint"></i> Verify Hashes
                    </button>
                    <button class="btn-select-all" onclick="modelDuplicatesManager.toggleSelectAllInGroup('${group.hash}')">
                        Select All
                    </button>
                </span>
            `;
            
            // Insert verification badge after the group title
            const headerFirstSpan = header.querySelector('span:first-child');
            headerFirstSpan.appendChild(verificationBadge);
            
            groupDiv.appendChild(header);
            
            // Create cards container
            const cardsDiv = document.createElement('div');
            cardsDiv.className = 'card-group-container';
            
            // Add scrollable class if there are many models in the group
            if (group.models.length > 6) {
                cardsDiv.classList.add('scrollable');
                
                // Add expand/collapse toggle button
                const toggleBtn = document.createElement('button');
                toggleBtn.className = 'group-toggle-btn';
                toggleBtn.innerHTML = '<i class="fas fa-chevron-down"></i>';
                toggleBtn.title = "Expand/Collapse";
                toggleBtn.onclick = function() {
                    cardsDiv.classList.toggle('scrollable');
                    this.innerHTML = cardsDiv.classList.contains('scrollable') ? 
                        '<i class="fas fa-chevron-down"></i>' : 
                        '<i class="fas fa-chevron-up"></i>';
                };
                groupDiv.appendChild(toggleBtn);
            }
            
            // Add all model cards in this group
            group.models.forEach(model => {
                const card = this.renderModelCard(model, group.hash);
                cardsDiv.appendChild(card);
            });
            
            groupDiv.appendChild(cardsDiv);
            modelGrid.appendChild(groupDiv);
            
            // Add event listener to the verify hashes button
            const verifyButton = header.querySelector('.btn-verify-hashes');
            if (verifyButton) {
                verifyButton.addEventListener('click', (e) => {
                    e.stopPropagation();
                    this.handleVerifyHashes(group);
                });
            }
        });
    }

    _getGroupFilePaths(group) {
        return new Set((group?.models || []).map(model => model.file_path));
    }

    _clearMismatchStateForGroup(group) {
        this._getGroupFilePaths(group).forEach(filePath => {
            this.mismatchedFiles.delete(filePath);
        });
    }

    _pruneVerificationState() {
        const visiblePaths = new Set();
        const visibleHashes = new Set();

        this.duplicateGroups.forEach(group => {
            visibleHashes.add(group.hash);
            this._getGroupFilePaths(group).forEach(filePath => visiblePaths.add(filePath));
        });

        Array.from(this.mismatchedFiles.keys()).forEach(filePath => {
            if (!visiblePaths.has(filePath)) {
                this.mismatchedFiles.delete(filePath);
            }
        });

        Array.from(this.selectedForDeletion).forEach(filePath => {
            if (!visiblePaths.has(filePath)) {
                this.selectedForDeletion.delete(filePath);
            }
        });

        Array.from(this.verifiedGroups).forEach(hash => {
            if (!visibleHashes.has(hash)) {
                this.verifiedGroups.delete(hash);
            }
        });
    }
    
    renderModelCard(model, groupHash) {
        // Create basic card structure
        const card = document.createElement('div');
        card.className = 'model-card duplicate';
        card.dataset.hash = model.sha256;
        card.dataset.filePath = model.file_path;
        
        // Check if this model is a mismatched file
        const isMismatched = this.mismatchedFiles.has(model.file_path);
        
        // Add mismatched class if needed
        if (isMismatched) {
            card.classList.add('hash-mismatch');
        }
        
        // Create card content using structure similar to createLoraCard in LoraCard.js
        const previewContainer = document.createElement('div');
        previewContainer.className = 'card-preview';
        
        // Determine if preview is a video
        const isVideo = model.preview_url && model.preview_url.endsWith('.mp4');
        let preview;
        
        if (isVideo) {
            // Create video element for MP4 previews
            preview = document.createElement('video');
            preview.loading = 'lazy';
            preview.controls = true;
            preview.muted = true;
            preview.loop = true;
            
            const source = document.createElement('source');
            source.src = model.preview_url;
            source.type = 'video/mp4';
            preview.appendChild(source);
        } else {
            // Create image element for standard previews
            preview = document.createElement('img');
            preview.loading = 'lazy';
            preview.alt = model.model_name;
            
            if (model.preview_url) {
                preview.src = model.preview_url;
            } else {
                // Use placeholder
                preview.src = '/loras_static/images/no-preview.png';
            }
        }
        
        // Add NSFW blur if needed
        if (model.preview_nsfw_level > 0) {
            preview.classList.add('nsfw');
        }
        
        previewContainer.appendChild(preview);
        
        // Add hash mismatch badge if needed
        if (isMismatched) {
            const mismatchBadge = document.createElement('div');
            mismatchBadge.className = 'mismatch-badge';
            mismatchBadge.innerHTML = '<i class="fas fa-exclamation-triangle"></i> Different Hash';
            previewContainer.appendChild(mismatchBadge);
        }
        
        // Mark as latest if applicable
        if (model.is_latest) {
            card.classList.add('latest');
        }
        
        // Move tooltip listeners to the preview container for consistent behavior
        // regardless of whether the preview is an image or video
        previewContainer.addEventListener('mouseover', () => this.renderTooltip(card, model));
        previewContainer.addEventListener('mouseout', () => {
            const tooltip = document.querySelector('.model-tooltip');
            if (tooltip) tooltip.remove();
        });
        
        // Add card footer with just model name
        const footer = document.createElement('div');
        footer.className = 'card-footer';
        
        const modelInfo = document.createElement('div');
        modelInfo.className = 'model-info';
        
        const modelName = document.createElement('span');
        modelName.className = 'model-name';
        modelName.textContent = model.model_name;
        modelInfo.appendChild(modelName);
        
        footer.appendChild(modelInfo);
        previewContainer.appendChild(footer);
        card.appendChild(previewContainer);
        
        // Add selection checkbox
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.className = 'selector-checkbox';
        checkbox.dataset.filePath = model.file_path;
        checkbox.dataset.groupHash = groupHash;
        
        // Check if already selected
        if (this.selectedForDeletion.has(model.file_path)) {
            checkbox.checked = true;
            card.classList.add('duplicate-selected');
        }
        
        // Disable checkbox for mismatched files
        if (isMismatched) {
            checkbox.disabled = true;
            checkbox.title = "This file has a different actual hash and can't be selected";
        }
        
        // Add change event to checkbox
        checkbox.addEventListener('change', (e) => {
            e.stopPropagation();
            this.toggleCardSelection(model.file_path, card, checkbox);
        });
        
        // Make the entire card clickable for selection
        card.addEventListener('click', (e) => {
            // Don't toggle if clicking on the checkbox directly or card actions
            if (e.target === checkbox || e.target.closest('.card-actions')) {
                return;
            }
            
            // Don't toggle if it's a mismatched file
            if (isMismatched) {
                return;
            }
            
            // Toggle checkbox state
            checkbox.checked = !checkbox.checked;
            this.toggleCardSelection(model.file_path, card, checkbox);
        });
        
        card.appendChild(checkbox);
        return card;
    }
    
    renderTooltip(card, model) {
        // Remove any existing tooltips
        const existingTooltip = document.querySelector('.model-tooltip');
        if (existingTooltip) existingTooltip.remove();
        
        // Create tooltip
        const tooltip = document.createElement('div');
        tooltip.className = 'model-tooltip';
        
        // Check if this model is a mismatched file and get the actual hash
        const isMismatched = this.mismatchedFiles.has(model.file_path);
        const actualHash = isMismatched ? this.mismatchedFiles.get(model.file_path) : null;
        
        // Add model information to tooltip
        let tooltipContent = `
            <div class="tooltip-header">${model.model_name}</div>
            <div class="tooltip-info">
                <div><strong>Version:</strong> ${model.civitai?.name || 'Unknown'}</div>
                <div><strong>Filename:</strong> ${model.file_name}</div>
                <div><strong>Path:</strong> ${model.file_path}</div>
                <div><strong>Base Model:</strong> ${model.base_model || 'Unknown'}</div>
                <div><strong>Modified:</strong> ${formatDate(model.modified)}</div>
                <div><strong>Metadata Hash:</strong> <span class="hash-value">${model.sha256}</span></div>
        `;
        
        // Add actual hash information if available
        if (isMismatched && actualHash) {
            tooltipContent += `<div class="hash-mismatch-info"><strong>Actual Hash:</strong> <span class="hash-value">${actualHash}</span></div>`;
        }
        
        tooltipContent += `</div>`;
        tooltip.innerHTML = tooltipContent;
        
        // Position tooltip relative to card
        const cardRect = card.getBoundingClientRect();
        tooltip.style.top = `${cardRect.top + window.scrollY - 10}px`;
        tooltip.style.left = `${cardRect.left + window.scrollX + cardRect.width + 10}px`;
        
        // Add tooltip to document
        document.body.appendChild(tooltip);
        
        // Check if tooltip is outside viewport and adjust if needed
        const tooltipRect = tooltip.getBoundingClientRect();
        if (tooltipRect.right > window.innerWidth) {
            tooltip.style.left = `${cardRect.left + window.scrollX - tooltipRect.width - 10}px`;
        }
    }
    
    // Helper method to toggle card selection state
    toggleCardSelection(filePath, card, checkbox) {
        if (checkbox.checked) {
            this.selectedForDeletion.add(filePath);
            card.classList.add('duplicate-selected');
        } else {
            this.selectedForDeletion.delete(filePath);
            card.classList.remove('duplicate-selected');
        }
        
        this.updateSelectedCount();
    }
    
    updateSelectedCount() {
        const selectedCountEl = document.getElementById('duplicatesSelectedCount');
        if (selectedCountEl) {
            selectedCountEl.textContent = this.selectedForDeletion.size;
        }
        
        // Update delete button state
        const deleteBtn = document.querySelector('.btn-delete-selected');
        if (deleteBtn) {
            deleteBtn.disabled = this.selectedForDeletion.size === 0;
            deleteBtn.classList.toggle('disabled', this.selectedForDeletion.size === 0);
        }
    }
    
    toggleSelectAllInGroup(hash) {
        const checkboxes = document.querySelectorAll(`.selector-checkbox[data-group-hash="${hash}"]`);
        const selectableCheckboxes = Array.from(checkboxes).filter(checkbox => !checkbox.disabled);
        const allSelected = selectableCheckboxes.length > 0 && selectableCheckboxes.every(checkbox => checkbox.checked);
        
        // If all are selected, deselect all; otherwise select all
        selectableCheckboxes.forEach(checkbox => {
            checkbox.checked = !allSelected;
            const filePath = checkbox.dataset.filePath;
            const card = checkbox.closest('.model-card');
            
            if (!allSelected) {
                this.selectedForDeletion.add(filePath);
                card.classList.add('duplicate-selected');
            } else {
                this.selectedForDeletion.delete(filePath);
                card.classList.remove('duplicate-selected');
            }
        });
        
        // Update the button text
        const button = document.querySelector(`.duplicate-group[data-hash="${hash}"] .btn-select-all`);
        if (button) {
            button.textContent = !allSelected ? "Deselect All" : "Select All";
        }
        
        this.updateSelectedCount();
    }
    
    async deleteSelectedDuplicates() {
        if (this.selectedForDeletion.size === 0) {
            showToast('toast.duplicates.noItemsSelected', { type: this.modelType }, 'info');
            return;
        }
        
        try {
            // Show the delete confirmation modal instead of a simple confirm
            const modelDuplicateDeleteCount = document.getElementById('modelDuplicateDeleteCount');
            if (modelDuplicateDeleteCount) {
              modelDuplicateDeleteCount.textContent = this.selectedForDeletion.size;
            }
            
            // Use the modal manager to show the confirmation modal
            modalManager.showModal('modelDuplicateDeleteModal');
        } catch (error) {
            console.error('Error preparing delete:', error);
            showToast('toast.duplicates.deleteError', { message: error.message }, 'error');
        }
    }
    
    // Execute deletion after confirmation
    async confirmDeleteDuplicates() {
        try {           
            // Close the modal
            modalManager.closeModal('modelDuplicateDeleteModal');
            
            // Prepare file paths for deletion
            const filePaths = Array.from(this.selectedForDeletion);
            
            // Call API to bulk delete
            const response = await fetch(`/api/lm/${this.modelType}/bulk-delete`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ file_paths: filePaths })
            });
            
            if (!response.ok) {
                throw new Error('Failed to delete selected models');
            }
            
            const data = await response.json();
            if (!data.success) {
                throw new Error(data.error || 'Unknown error deleting models');
            }

            const batchIds = !data.batch_id && Array.isArray(data.batch_ids) && data.batch_ids.length
                ? data.batch_ids
                : null;

            if (data.batch_id || batchIds) {
                // One undo action restores the whole selected group
                const refreshFn = () => resetAndReload(true);
                const onAction = data.batch_id
                    ? () => handleUndoDelete(data.batch_id, refreshFn)
                    : async () => {
                        for (const id of batchIds) {
                            const succeeded = await handleUndoDelete(id, null, { showToast: false, refresh: false });
                            if (!succeeded) {
                                showToast('toast.undo.failed', { error: '' }, 'error');
                                return;
                            }
                        }
                        refreshFn();
                        showToast('toast.undo.restored', {}, 'success');
                    };
                showActionToast('toast.undo.deletedBulk', { count: data.total_deleted }, 'success', {
                    actionText: translate('toast.undo.action'),
                    onAction,
                });
            } else {
                showToast('toast.duplicates.deleteSuccess', { count: data.total_deleted, type: this.modelType }, 'success');
            }
            
            // If models were successfully deleted
            if (data.total_deleted > 0) {
                await resetAndReload(true);
                
                // Check if there are still duplicates
                try {
                    const endpoint = `/api/lm/${this.modelType}/find-duplicates`;
                    const dupResponse = await fetch(endpoint);
                    
                    if (!dupResponse.ok) {
                        throw new Error(`Failed to get duplicates: ${dupResponse.statusText}`);
                    }
                    
                    const dupData = await dupResponse.json();
                    const remainingDuplicatesCount = (dupData.duplicates || []).length;
                    
                    // Update badge count
                    this.updateDuplicatesBadge(remainingDuplicatesCount);
                    
                    // If no more duplicates, exit duplicate mode
                    if (remainingDuplicatesCount === 0) {
                        this.exitDuplicateMode();
                    } else {
                        // If duplicates remain, refresh duplicate groups display
                        this.duplicateGroups = dupData.duplicates || [];
                        this.selectedForDeletion.clear();
                        this.renderDuplicateGroups();
                        this.updateSelectedCount();
                    }
                } catch (error) {
                    console.error('Error checking remaining duplicates:', error);
                }
            }
            
        } catch (error) {
            console.error('Error deleting models:', error);
            showToast('toast.duplicates.deleteFailed', { type: this.modelType, message: error.message }, 'error');
        }
    }
    
    // Public method to update the badge after refresh
    updateDuplicatesBadgeAfterRefresh() {
        // Use this method after refresh operations
        this.checkDuplicatesCount();
    }

    // Add this new method for tooltip behavior
    setupHelpTooltip() {
      const helpIcon = document.getElementById('duplicatesHelp');
      const helpTooltip = document.getElementById('duplicatesHelpTooltip');
      
      if (!helpIcon || !helpTooltip) return;
      
      // Clean up existing handlers first
      this.cleanupHelpTooltipHandlers();
      
      // Create new handler functions and store references
      this.helpTooltipHandlers.mouseenter = (e) => {
          // Get the container's positioning context
          const bannerContent = helpIcon.closest('.banner-content');
          
          // Get positions relative to the viewport
          const iconRect = helpIcon.getBoundingClientRect();
          const bannerRect = bannerContent.getBoundingClientRect();
          
          // Set initial position relative to the banner content
          helpTooltip.style.display = 'block';
          helpTooltip.style.top = `${iconRect.bottom - bannerRect.top + 10}px`;
          helpTooltip.style.left = `${iconRect.left - bannerRect.left - 10}px`;
          
          // Check if the tooltip is going off-screen to the right
          const tooltipRect = helpTooltip.getBoundingClientRect();
          const viewportWidth = window.innerWidth;
          
          if (tooltipRect.right > viewportWidth - 20) {
              // Reposition relative to container if too close to right edge
              helpTooltip.style.left = `${bannerContent.offsetWidth - tooltipRect.width - 20}px`;
          }
      };
      
      this.helpTooltipHandlers.mouseleave = () => {
          helpTooltip.style.display = 'none';
      };
      
      this.helpTooltipHandlers.click = (e) => {
          if (!helpIcon.contains(e.target)) {
              helpTooltip.style.display = 'none';
          }
      };
      
      // Add event listeners
      helpIcon.addEventListener('mouseenter', this.helpTooltipHandlers.mouseenter);
      helpIcon.addEventListener('mouseleave', this.helpTooltipHandlers.mouseleave);
      document.addEventListener('click', this.helpTooltipHandlers.click);
    }

    // Handle verify hashes button click
    async handleVerifyHashes(group) {
        try {
            const groupHash = group.hash;
            
            // Check if already verified
            if (this.verifiedGroups.has(groupHash)) {
                showToast('toast.models.verificationAlreadyDone', {}, 'info');
                return;
            }
            
            // Show loading state
            state.loadingManager.showSimpleLoading('Verifying hashes...');
            
            // Get file paths for all models in the group
            const filePaths = group.models.map(model => model.file_path);
            
            // Make API request to verify hashes
            const response = await fetch(`/api/lm/${this.modelType}/verify-duplicates`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ file_paths: filePaths })
            });
            
            if (!response.ok) {
                throw new Error(`Verification failed: ${response.statusText}`);
            }
            
            const data = await response.json();
            
            if (!data.success) {
                throw new Error(data.error || 'Unknown error during verification');
            }
            
            // Process verification results
            const verifiedAsDuplicates = data.verified_as_duplicates;
            const mismatchedFiles = data.mismatched_files || [];

            this._clearMismatchStateForGroup(group);
            
            // Update mismatchedFiles map
            if (data.new_hash_map) {
                Object.entries(data.new_hash_map).forEach(([path, hash]) => {
                    this.mismatchedFiles.set(path, hash);
                    this.selectedForDeletion.delete(path);
                });
            }
            
            // Mark this group as verified
            this.verifiedGroups.add(groupHash);
            
            // Re-render the duplicate groups to show verification status
            this.renderDuplicateGroups();
            this.updateSelectedCount();
            
            // Show appropriate toast message
            if (mismatchedFiles.length > 0) {
                showToast('toast.models.verificationCompleteMismatch', { count: mismatchedFiles.length }, 'warning');
            } else {
                showToast('toast.models.verificationCompleteSuccess', {}, 'success');
            }
            
        } catch (error) {
            console.error('Error verifying hashes:', error);
            showToast('toast.models.verificationFailed', { message: error.message }, 'error');
        } finally {
            // Hide loading state
            state.loadingManager.hide();
        }
    }
    
    // Add this new method for badge toggle setup
    setupBadgeToggle() {
        const toggleControl = document.getElementById('badgeToggleControl');
        const toggleInput = document.getElementById('badgeToggleInput');
        
        if (!toggleControl || !toggleInput) return;
        
        // Clean up existing handler first
        this.cleanupBadgeToggleHandler();
        
        // Set initial state based on stored preference (default to true/checked)
        toggleInput.checked = this.showBadge;
        
        // Create and store the handler function
        this.badgeToggleHandler = (e) => {
            this.showBadge = e.target.checked;
            setShowDuplicatesNotification(this.showBadge);
            
            // Update badge visibility immediately if not in duplicate mode
            if (!this.inDuplicateMode) {
                this.updateDuplicatesBadge(this.duplicateGroups.length);
            }
            
            showToast(
                this.showBadge ? 'Duplicates notification will be shown' : 'Duplicates notification will be hidden',
                'info'
            );
        };
        
        // Add change event listener
        toggleInput.addEventListener('change', this.badgeToggleHandler);
    }
    
    // Clean up all event handlers
    cleanupEventHandlers() {
        this.cleanupBadgeToggleHandler();
        this.cleanupHelpTooltipHandlers();
    }
    
    // Clean up badge toggle event handler
    cleanupBadgeToggleHandler() {
        if (this.badgeToggleHandler) {
            const toggleInput = document.getElementById('badgeToggleInput');
            if (toggleInput) {
                toggleInput.removeEventListener('change', this.badgeToggleHandler);
            }
            this.badgeToggleHandler = null;
        }
    }
    
    // Clean up help tooltip event handlers
    cleanupHelpTooltipHandlers() {
        const helpIcon = document.getElementById('duplicatesHelp');
        
        if (helpIcon && this.helpTooltipHandlers.mouseenter) {
            helpIcon.removeEventListener('mouseenter', this.helpTooltipHandlers.mouseenter);
        }
        
        if (helpIcon && this.helpTooltipHandlers.mouseleave) {
            helpIcon.removeEventListener('mouseleave', this.helpTooltipHandlers.mouseleave);
        }
        
        if (this.helpTooltipHandlers.click) {
            document.removeEventListener('click', this.helpTooltipHandlers.click);
        }
        
        // Reset handler references
        this.helpTooltipHandlers = {
            mouseenter: null,
            mouseleave: null,
            click: null
        };
        
        // Hide tooltip if it's visible
        const helpTooltip = document.getElementById('duplicatesHelpTooltip');
        if (helpTooltip) {
            helpTooltip.style.display = 'none';
        }
    }
}
