import { BaseContextMenu } from './BaseContextMenu.js';
import { state } from '../../state/index.js';
import { bulkManager } from '../../managers/BulkManager.js';
import { updateElementText, translate } from '../../utils/i18nHelpers.js';
import { bulkMissingLoraDownloadManager } from '../../managers/BulkMissingLoraDownloadManager.js';
import { showToast } from '../../utils/uiHelpers.js';
import { getModelApiClient } from '../../api/modelApiFactory.js';

export class BulkContextMenu extends BaseContextMenu {
    constructor() {
        super('bulkContextMenu', '.model-card.selected');
        this.setupBulkMenuItems();
    }

    setupBulkMenuItems() {
        if (!this.menu) return;

        // Update menu items visibility based on current model type
        this.updateMenuItemsForModelType();
        
        // Update selected count in header
        this.updateSelectedCountHeader();
    }

    updateMenuItemsForModelType() {
        const currentModelType = state.currentPageType;
        const config = bulkManager.actionConfig[currentModelType];
        
        if (!config) return;

        // Update button visibility based on model type
        const addTagsItem = this.menu.querySelector('[data-action="add-tags"]');
        const setBaseModelItem = this.menu.querySelector('[data-action="set-base-model"]');
        const setContentRatingItem = this.menu.querySelector('[data-action="set-content-rating"]');
        const sendToWorkflowAppendItem = this.menu.querySelector('[data-action="send-to-workflow-append"]');
        const sendToWorkflowReplaceItem = this.menu.querySelector('[data-action="send-to-workflow-replace"]');
        const copyAllItem = this.menu.querySelector('[data-action="copy-all"]');
        const refreshAllItem = this.menu.querySelector('[data-action="refresh-all"]');
        const checkUpdatesItem = this.menu.querySelector('[data-action="check-updates"]');
        const moveAllItem = this.menu.querySelector('[data-action="move-all"]');
        const autoOrganizeItem = this.menu.querySelector('[data-action="auto-organize"]');
        const deleteAllItem = this.menu.querySelector('[data-action="delete-all"]');
        const downloadMissingLorasItem = this.menu.querySelector('[data-action="download-missing-loras"]');
        const repairMetadataItem = this.menu.querySelector('[data-action="repair-metadata"]');
        const reimportMetadataItem = this.menu.querySelector('[data-action="reimport-metadata"]');
        const rematchMetadataItem = this.menu.querySelector('[data-action="rematch-metadata"]');

        if (repairMetadataItem) {
            repairMetadataItem.style.display = config.repairMetadata ? 'flex' : 'none';
        }
        if (reimportMetadataItem) {
            reimportMetadataItem.style.display = config.reimportMetadata ? 'flex' : 'none';
        }
        if (rematchMetadataItem) {
            rematchMetadataItem.style.display = config.rematchMetadata ? 'flex' : 'none';
        }

        const isEmbeddings = currentModelType === 'embeddings';
        if (sendToWorkflowAppendItem) {
            sendToWorkflowAppendItem.style.display = config.sendToWorkflow ? 'flex' : 'none';
        }
        if (sendToWorkflowReplaceItem) {
            sendToWorkflowReplaceItem.style.display = (config.sendToWorkflow && !isEmbeddings) ? 'flex' : 'none';
        }
        if (copyAllItem) {
            copyAllItem.style.display = config.copyAll ? 'flex' : 'none';
        }

        // Submenu parent - for embeddings, collapse into a direct item (no replace choice)
        const sendToWorkflowSubmenu = this.menu.querySelector('[data-has-submenu="send-to-workflow"]');
        if (sendToWorkflowSubmenu) {
            const hasWorkflowActions = config.sendToWorkflow || config.copyAll;
            if (isEmbeddings && config.sendToWorkflow && !config.copyAll) {
                sendToWorkflowSubmenu.classList.remove('has-submenu');
                sendToWorkflowSubmenu.removeAttribute('data-has-submenu');
                sendToWorkflowSubmenu.dataset.action = 'send-to-workflow-append';
                const arrow = sendToWorkflowSubmenu.querySelector('.submenu-arrow');
                if (arrow) arrow.style.display = 'none';
                const submenu = sendToWorkflowSubmenu.querySelector('.context-submenu');
                if (submenu) submenu.style.display = 'none';
                sendToWorkflowSubmenu.style.display = 'flex';
            } else {
                sendToWorkflowSubmenu.style.display = hasWorkflowActions ? 'flex' : 'none';
            }
        }

        if (refreshAllItem) {
            refreshAllItem.style.display = config.refreshAll ? 'flex' : 'none';
        }
        if (checkUpdatesItem) {
            checkUpdatesItem.style.display = config.checkUpdates ? 'flex' : 'none';
        }
        if (moveAllItem) {
            moveAllItem.style.display = config.moveAll ? 'flex' : 'none';
        }
        if (autoOrganizeItem) {
            autoOrganizeItem.style.display = config.autoOrganize ? 'flex' : 'none';
        }
        if (deleteAllItem) {
            deleteAllItem.style.display = config.deleteAll ? 'flex' : 'none';
        }
        if (addTagsItem) {
            addTagsItem.style.display = config.addTags ? 'flex' : 'none';
        }
        if (setBaseModelItem) {
            setBaseModelItem.style.display = 'flex'; // Base model editing is available for all model types
        }
        if (setContentRatingItem) {
            setContentRatingItem.style.display = config.setContentRating ? 'flex' : 'none';
        }

        const setFavoriteItem = this.menu.querySelector('[data-action="set-favorite"]');

        if (setFavoriteItem && config.setFavorite) {
            setFavoriteItem.style.display = 'flex';

            const total = state.selectedModels.size;
            const favoritedCount = this.countFavoritedInSelection();
            const allFavorited = total > 0 && favoritedCount === total;

            const icon = setFavoriteItem.querySelector('i');
            const label = setFavoriteItem.querySelector('span');

            if (allFavorited) {
                if (icon) { icon.className = 'far fa-star'; }
                if (label) { label.textContent = translate('loras.bulkOperations.unfavorite'); }
            } else {
                if (icon) { icon.className = 'fas fa-star'; }
                if (label) {
                    label.textContent = favoritedCount > 0
                        ? translate('loras.bulkOperations.setFavoriteCount', { favorited: favoritedCount, total })
                        : translate('loras.bulkOperations.setFavorite');
                }
            }
        } else if (setFavoriteItem) {
            setFavoriteItem.style.display = 'none';
        }

        if (downloadMissingLorasItem) {
            // Only show for recipes page
            downloadMissingLorasItem.style.display = currentModelType === 'recipes' ? 'flex' : 'none';
        }

        const downloadExampleImagesSubmenu = this.menu.querySelector('[data-has-submenu="download-example-images"]');
        if (downloadExampleImagesSubmenu) {
            // Show on model pages (loras, checkpoints, embeddings), hide on recipes
            downloadExampleImagesSubmenu.style.display = ['loras', 'checkpoints', 'embeddings'].includes(currentModelType) ? 'flex' : 'none';
        }

        const skipMetadataRefreshItem = this.menu.querySelector('[data-action="skip-metadata-refresh"]');
        const resumeMetadataRefreshItem = this.menu.querySelector('[data-action="resume-metadata-refresh"]');

        if (skipMetadataRefreshItem && resumeMetadataRefreshItem) {
            if (!config.skipMetadataRefresh) {
                skipMetadataRefreshItem.style.display = 'none';
                resumeMetadataRefreshItem.style.display = 'none';
            } else {
                const skipCount = this.countSkipStatus(true);
                const resumeCount = this.countSkipStatus(false);
                const totalCount = skipCount + resumeCount;

                if (skipCount === totalCount) {
                    skipMetadataRefreshItem.style.display = 'none';
                    resumeMetadataRefreshItem.style.display = 'flex';
                    resumeMetadataRefreshItem.querySelector('span').textContent = translate(
                        'loras.bulkOperations.resumeMetadataRefresh'
                    );
                } else if (resumeCount === totalCount) {
                    skipMetadataRefreshItem.style.display = 'flex';
                    resumeMetadataRefreshItem.style.display = 'none';
                    skipMetadataRefreshItem.querySelector('span').textContent = translate(
                        'loras.bulkOperations.skipMetadataRefresh'
                    );
                } else {
                    skipMetadataRefreshItem.style.display = 'flex';
                    resumeMetadataRefreshItem.style.display = 'flex';
                    skipMetadataRefreshItem.querySelector('span').textContent = translate(
                        'loras.bulkOperations.skipMetadataRefreshCount',
                        { count: resumeCount }
                    );
                    resumeMetadataRefreshItem.querySelector('span').textContent = translate(
                        'loras.bulkOperations.resumeMetadataRefreshCount',
                        { count: skipCount }
                    );
                }
            }
        }

        // Hide empty sections
        this.menu.querySelectorAll('.context-menu-section').forEach(section => {
            const items = Array.from(section.querySelectorAll('.context-menu-item'))
                .filter(item => !item.closest('.context-submenu'));
            const allHidden = items.length > 0 && items.every(item => item.style.display === 'none');
            section.style.display = allHidden ? 'none' : '';
        });
    }

    updateSelectedCountHeader() {
        const headerElement = this.menu.querySelector('.bulk-context-header');
        if (headerElement) {
            updateElementText(headerElement, 'loras.bulkOperations.selected', { count: state.selectedModels.size });
        }
    }

    countSkipStatus(skipState) {
        let count = 0;
        for (const filePath of state.selectedModels) {
            const escapedPath = window.CSS && typeof window.CSS.escape === 'function'
                ? window.CSS.escape(filePath)
                : filePath.replace(/["\\]/g, '\\$&');
            const card = document.querySelector(`.model-card[data-filepath="${escapedPath}"]`);
            if (card) {
                const isSkipped = card.dataset.skip_metadata_refresh === 'true';
                if (isSkipped === skipState) {
                    count++;
                }
            }
        }
        return count;
    }

    countFavoritedInSelection() {
        let count = 0;
        for (const filePath of state.selectedModels) {
            const escapedPath = window.CSS && typeof window.CSS.escape === 'function'
                ? window.CSS.escape(filePath)
                : filePath.replace(/["\\]/g, '\\$&');
            const card = document.querySelector(`.model-card[data-filepath="${escapedPath}"]`);
            if (card && card.dataset.favorite === 'true') {
                count++;
            }
        }
        return count;
    }

    showMenu(x, y, card) {
        this.updateMenuItemsForModelType();
        this.updateSelectedCountHeader();
        super.showMenu(x, y, card);
    }

    handleMenuAction(action, menuItem) {
        switch (action) {
            case 'add-tags':
                bulkManager.showBulkAddTagsModal();
                break;
            case 'set-base-model':
                bulkManager.showBulkBaseModelModal();
                break;
            case 'set-content-rating':
                bulkManager.showBulkContentRatingSelector();
                break;
            case 'send-to-workflow-append':
                bulkManager.sendAllModelsToWorkflow(false);
                break;
            case 'send-to-workflow-replace':
                bulkManager.sendAllModelsToWorkflow(true);
                break;
            case 'copy-all':
                bulkManager.copyAllModelsSyntax();
                break;
            case 'refresh-all':
                bulkManager.refreshAllMetadata();
                break;
            case 'check-updates':
                bulkManager.checkUpdatesForSelectedModels();
                break;
            case 'move-all':
                window.moveManager.showMoveModal('bulk');
                break;
            case 'auto-organize':
                bulkManager.autoOrganizeSelectedModels();
                break;
            case 'skip-metadata-refresh':
                bulkManager.setSkipMetadataRefresh(true);
                break;
            case 'resume-metadata-refresh':
                bulkManager.setSkipMetadataRefresh(false);
                break;
            case 'enrich-hf-llm-bulk':
                this.enrichBulkWithAgent();
                break;
            case 'delete-all':
                bulkManager.showBulkDeleteModal();
                break;
            case 'repair-metadata':
                bulkManager.repairSelectedRecipes();
                break;
            case 'rematch-metadata':
                bulkManager.rematchSelectedRecipes();
                break;
            case 'reimport-metadata':
                bulkManager.reimportSelectedRecipes();
                break;
            case 'set-favorite': {
                const allFavorited = this.countFavoritedInSelection() === state.selectedModels.size;
                bulkManager.setBulkFavorites(!allFavorited);
                break;
            }
            case 'download-missing-loras':
                this.handleDownloadMissingLoras();
                break;
            case 'download-missing-example-images':
                this.handleDownloadExampleImages({ force: false });
                break;
            case 'download-example-images':
                this.handleDownloadExampleImages({ force: true });
                break;
            case 'clear':
                bulkManager.clearSelection();
                break;
            default:
                console.warn(`Unknown bulk action: ${action}`);
        }
    }

    /**
     * Handle downloading missing LoRAs for selected recipes
     */
    async handleDownloadMissingLoras() {
        if (state.selectedModels.size === 0) {
            return;
        }

        // Get selected recipes from the virtual scroller
        const selectedRecipes = [];
        state.selectedModels.forEach(filePath => {
            const card = document.querySelector(`.model-card[data-filepath="${CSS.escape(filePath)}"]`);
            if (card && card.recipeData) {
                selectedRecipes.push(card.recipeData);
            }
        });

        if (selectedRecipes.length === 0) {
            // Try to get recipes from virtual scroller state
            const items = state.virtualScroller?.items || [];
            items.forEach(recipe => {
                if (recipe.file_path && state.selectedModels.has(recipe.file_path)) {
                    selectedRecipes.push(recipe);
                }
            });
        }

        if (selectedRecipes.length === 0) {
            showToast('toast.recipes.noRecipesSelected', {}, 'warning');
            return;
        }

        await bulkMissingLoraDownloadManager.downloadMissingLoras(selectedRecipes);
    }

    async handleDownloadExampleImages({ force = true } = {}) {
        if (state.selectedModels.size === 0) {
            return;
        }

        const hashes = new Set();
        for (const filePath of state.selectedModels) {
            const escapedPath = CSS.escape(filePath);
            const card = document.querySelector(`.model-card[data-filepath="${escapedPath}"]`);
            if (card?.dataset?.sha256) {
                hashes.add(card.dataset.sha256);
            }
        }

        if (hashes.size === 0) {
            showToast('No valid model hashes found in selection', {}, 'warning');
            return;
        }

        try {
            const apiClient = getModelApiClient();
            await apiClient.downloadExampleImages([...hashes], null, { force });
        } catch (error) {
            console.error('Bulk download example images failed:', error);
        }
    }

    /**
     * Enrich metadata for selected models via LLM agent skill.
     */
    async enrichBulkWithAgent() {
        if (state.selectedModels.size === 0) {
            return;
        }

        const { agentManager } = await import('../../managers/AgentManager.js');

        const configured = await agentManager.isLlmConfigured();
        if (!configured) {
            showToast('toast.agent.llmNotConfigured', {}, 'warning');
            return;
        }

        const modelPaths = [...state.selectedModels];

        agentManager.connect();

        const progressUI = state.loadingManager.showEnhancedProgress(
            `Enriching metadata for ${modelPaths.length} models...`
        );

        function cleanupCallbacks() {
            const pIdx = agentManager.progressCallbacks.indexOf(onProgress);
            if (pIdx >= 0) agentManager.progressCallbacks.splice(pIdx, 1);
            const cIdx = agentManager.completeCallbacks.indexOf(onComplete);
            if (cIdx >= 0) agentManager.completeCallbacks.splice(cIdx, 1);
            const eIdx = agentManager.errorCallbacks.indexOf(onError);
            if (eIdx >= 0) agentManager.errorCallbacks.splice(eIdx, 1);
        }

        const onProgress = (data) => {
            if (data.status === 'processing' && data.current_path && data.updated_data && Object.keys(data.updated_data).length > 0) {
                if (state.virtualScroller?.updateSingleItem) {
                    state.virtualScroller.updateSingleItem(data.current_path, data.updated_data);
                }
                const pct = data.total > 0 ? Math.floor((data.processed / data.total) * 100) : 0;
                const name = data.current_path.split('/').pop();
                progressUI.updateProgress(pct, name, `Processing ${data.processed}/${data.total}: ${name}`);
            }
        };
        agentManager.onProgress(onProgress);

        const onComplete = (data) => {
            cleanupCallbacks();

            if (data.status === 'completed') {
                if (state.bulkMode) bulkManager.toggleBulkMode();
                progressUI.complete(data.summary || 'Enrich complete');
                showToast(
                    'toast.agent.enrichComplete',
                    { summary: data.summary || 'Done' },
                    'success'
                );
            }
        };
        agentManager.onComplete(onComplete);

        const onError = (data) => {
            cleanupCallbacks();
            if (state.bulkMode) bulkManager.toggleBulkMode();
            state.loadingManager.hide();
            showToast(
                'toast.agent.enrichFailed',
                { error: data.error || 'Unknown error' },
                'error'
            );
        };
        agentManager.onError(onError);

        try {
            await agentManager.executeSkill('enrich_hf_metadata', modelPaths);
        } catch (error) {
            cleanupCallbacks();
            if (state.bulkMode) bulkManager.toggleBulkMode();
            state.loadingManager.hide();
            showToast(
                'toast.agent.enrichFailed',
                { error: error.message },
                'error'
            );
        }
    }
}
