/**
 * @file ui.js
 * @description Centralizes UI component classes for modals and common UI patterns.
 * This module exports singleton instances of `ModalManager` and `UIPatterns`
 * to ensure consistent UI behavior across the application.
 */

/**
 * Manages the display and interaction of various modals across the application.
 * This class centralizes modal logic to ensure consistency and ease of use.
 * It assumes specific HTML structures for modals (e.g., resultModal, progressModal).
 */
class ModalManager {
    /**
     * Shows a generic modal by its ID.
     * @param {string} modalId The ID of the modal element to show.
     */
    show(modalId) {
        const modal = document.getElementById(modalId);
        if (modal) {
            modal.classList.remove("hidden");
        } else {
            console.error(`Modal with ID "${modalId}" not found.`);
        }
    }

    /**
     * Hides a generic modal by its ID.
     * @param {string} modalId The ID of the modal element to hide.
     */
    hide(modalId) {
        const modal = document.getElementById(modalId);
        if (modal) {
            modal.classList.add("hidden");
        } else {
            console.error(`Modal with ID "${modalId}" not found.`);
        }
    }

    /**
     * Shows a confirmation dialog. This is a versatile method for 'Are you sure?' style prompts.
     * It dynamically sets the title, message, and confirm action for a generic confirmation modal.
     * @param {object} options - The options for the confirmation modal.
     * @param {string} options.modalId - The ID of the confirmation modal element (e.g., 'resetModal', 'deleteConfirmModal').
     * @param {string} options.title - The title to display in the modal header.
     * @param {string} options.message - The message to display in the modal body. Can contain HTML.
     * @param {function} options.onConfirm - The callback function to execute when the confirm button is clicked.
     * @param {boolean} [options.disableConfirm=false] - Whether the confirm button should be initially disabled.
     */
    showConfirm({ modalId, title, message, onConfirm, disableConfirm = false }) {
        const modalElement = document.getElementById(modalId);
        if (!modalElement) {
            console.error(`Confirmation modal with ID "${modalId}" not found.`);
            return;
        }

        const titleElement = modalElement.querySelector('[id$="ModalTitle"]');
        const messageElement = modalElement.querySelector('[id$="ModalMessage"]');
        const confirmButton = modalElement.querySelector('[id^="confirm"]');

        if (!titleElement || !messageElement || !confirmButton) {
            console.error(`Modal "${modalId}" is missing required child elements (title, message, or confirm button).`);
            return;
        }

        titleElement.textContent = title;
        messageElement.innerHTML = message;
        confirmButton.disabled = disableConfirm;

        // Re-clone the button to remove old event listeners and attach the new one.
        const newConfirmButton = confirmButton.cloneNode(true);
        confirmButton.parentNode.replaceChild(newConfirmButton, confirmButton);
        newConfirmButton.onclick = () => onConfirm();

        this.show(modalId);
    }

    /**
     * Shows a result modal to indicate the outcome of an operation (success or failure).
     * @param {boolean} success - If true, displays a success icon and title; otherwise, shows failure indicators.
     * @param {string|Node} message - The message to display. Can be a simple string or a complex DOM Node for rich content.
     * @param {boolean} [autoReload=false] - If true, the page will automatically reload when the modal is closed.
     */
    showResult(success, message, autoReload = false) {
        const modalElement = document.getElementById("resultModal");
        if (!modalElement) {
            console.error("Result modal with ID 'resultModal' not found.");
            return;
        }

        const titleElement = document.getElementById("resultModalTitle");
        const messageElement = document.getElementById("resultModalMessage");
        const iconElement = document.getElementById("resultIcon");
        const confirmButton = document.getElementById("resultModalConfirmBtn");

        if (!titleElement || !messageElement || !iconElement || !confirmButton) {
            console.error("Result modal is missing required child elements.");
            return;
        }

        titleElement.textContent = success ? "操作成功" : "操作失败";

        if (success) {
            iconElement.innerHTML = '<i class="fas fa-check-circle text-success-500"></i>';
            iconElement.className = "text-6xl mb-3 text-success-500";
        } else {
            iconElement.innerHTML = '<i class="fas fa-times-circle text-danger-500"></i>';
            iconElement.className = "text-6xl mb-3 text-danger-500";
        }

        messageElement.innerHTML = "";
        if (typeof message === "string") {
            const messageDiv = document.createElement("div");
            messageDiv.innerText = message; // Use innerText for security with plain strings
            messageElement.appendChild(messageDiv);
        } else if (message instanceof Node) {
            messageElement.appendChild(message); // Append if it's already a DOM node
        } else {
            const messageDiv = document.createElement("div");
            messageDiv.innerText = String(message);
            messageElement.appendChild(messageDiv);
        }

        confirmButton.onclick = () => this.closeResult(autoReload);
        this.show("resultModal");
    }

    /**
     * Closes the result modal.
     * @param {boolean} [reload=false] - If true, reloads the page after closing the modal.
     */
    closeResult(reload = false) {
        this.hide("resultModal");
        if (reload) {
            location.reload();
        }
    }

    /**
     * Shows and initializes the progress modal for long-running operations.
     * @param {string} title - The title to display for the progress modal.
     */
    showProgress(title) {
        const modal = document.getElementById("progressModal");
        if (!modal) {
            console.error("Progress modal with ID 'progressModal' not found.");
            return;
        }
        const titleElement = document.getElementById("progressModalTitle");
        const statusText = document.getElementById("progressStatusText");
        const progressBar = document.getElementById("progressBar");
        const progressPercentage = document.getElementById("progressPercentage");
        const progressLog = document.getElementById("progressLog");
        const closeButton = document.getElementById("progressModalCloseBtn");
        const closeIcon = document.getElementById("closeProgressModalBtn");

        if (!titleElement || !statusText || !progressBar || !progressPercentage || !progressLog || !closeButton || !closeIcon) {
            console.error("Progress modal is missing required child elements.");
            return;
        }

        titleElement.textContent = title;
        statusText.textContent = "准备开始...";
        progressBar.style.width = "0%";
        progressPercentage.textContent = "0%";
        progressLog.innerHTML = "";
        closeButton.disabled = true;
        closeIcon.disabled = true;

        this.show("progressModal");
    }

    /**
     * Updates the progress bar and status text within the progress modal.
     * @param {number} processed - The number of items that have been processed.
     * @param {number} total - The total number of items to process.
     * @param {string} status - The current status message to display.
     */
    updateProgress(processed, total, status) {
        const modal = document.getElementById("progressModal");
        if (!modal || modal.classList.contains('hidden')) return;

        const progressBar = document.getElementById("progressBar");
        const progressPercentage = document.getElementById("progressPercentage");
        const statusText = document.getElementById("progressStatusText");
        const closeButton = document.getElementById("progressModalCloseBtn");
        const closeIcon = document.getElementById("closeProgressModalBtn");

        const percentage = total > 0 ? Math.round((processed / total) * 100) : 0;
        progressBar.style.width = `${percentage}%`;
        progressPercentage.textContent = `${percentage}%`;
        statusText.textContent = status;

        if (processed === total) {
            closeButton.disabled = false;
            closeIcon.disabled = false;
        }
    }

    /**
     * Adds a log entry to the progress modal's log area.
     * @param {string} message - The log message to append.
     * @param {boolean} [isError=false] - If true, styles the log entry as an error.
     */
    addProgressLog(message, isError = false) {
        const progressLog = document.getElementById("progressLog");
        if (!progressLog) return;

        const logEntry = document.createElement("div");
        logEntry.textContent = message;
        logEntry.className = isError ? "text-danger-600" : "text-gray-700";
        progressLog.appendChild(logEntry);
        progressLog.scrollTop = progressLog.scrollHeight; // Auto-scroll to the latest log
    }

    /**
     * Closes the progress modal.
     * @param {boolean} [reload=false] - If true, reloads the page after closing.
     */
    closeProgress(reload = false) {
        this.hide("progressModal");
        if (reload) {
            location.reload();
        }
    }
}

/**
 * Provides a collection of common UI patterns and animations.
 * This class includes helpers for creating engaging and consistent user experiences,
 * such as animated counters and collapsible sections.
 */
class UIPatterns {
    /**
     * Animates numerical values in elements from 0 to their target number.
     * The target number is read from the element's text content.
     * @param {string} selector - The CSS selector for the elements to animate (e.g., '.stat-value').
     * @param {number} [duration=1500] - The duration of the animation in milliseconds.
     */
    animateCounters(selector = ".stat-value", duration = 1500) {
        const statValues = document.querySelectorAll(selector);
        statValues.forEach((valueElement) => {
            const finalValue = parseInt(valueElement.textContent, 10);
            if (isNaN(finalValue)) return;

            if (!valueElement.dataset.originalValue) {
                valueElement.dataset.originalValue = valueElement.textContent;
            }

            let startValue = 0;
            const startTime = performance.now();

            const updateCounter = (currentTime) => {
                const elapsedTime = currentTime - startTime;
                if (elapsedTime < duration) {
                    const progress = elapsedTime / duration;
                    const easeOutValue = 1 - Math.pow(1 - progress, 3); // Ease-out cubic
                    const currentValue = Math.floor(easeOutValue * finalValue);
                    valueElement.textContent = currentValue;
                    requestAnimationFrame(updateCounter);
                } else {
                    valueElement.textContent = valueElement.dataset.originalValue; // Ensure final value is accurate
                }
            };
            requestAnimationFrame(updateCounter);
        });
    }

    /**
     * Toggles the visibility of a content section with a smooth height animation.
     * It expects a specific HTML structure where the header and content are within a common parent (e.g., a card).
     * The content element should have a `collapsed` class when hidden.
     * @param {HTMLElement} header - The header element that was clicked to trigger the toggle.
     */
    toggleSection(header) {
        const card = header.closest(".stats-card");
        if (!card) return;

        const content = card.querySelector(".key-content");
        const toggleIcon = header.querySelector(".toggle-icon");

        if (!content || !toggleIcon) {
            console.error("Toggle section failed: Content or icon element not found.", { header });
            return;
        }

        const isCollapsed = content.classList.contains("collapsed");
        toggleIcon.classList.toggle("collapsed", !isCollapsed);

        if (isCollapsed) {
            // Expand
            content.classList.remove("collapsed");
            content.style.maxHeight = null;
            content.style.opacity = null;
            content.style.paddingTop = null;
            content.style.paddingBottom = null;
            content.style.overflow = "hidden";

            requestAnimationFrame(() => {
                const targetHeight = content.scrollHeight;
                content.style.maxHeight = `${targetHeight}px`;
                content.style.opacity = "1";
                content.style.paddingTop = "1rem"; // Assumes p-4, adjust if needed
                content.style.paddingBottom = "1rem";

                content.addEventListener("transitionend", function onExpansionEnd() {
                    content.removeEventListener("transitionend", onExpansionEnd);
                    if (!content.classList.contains("collapsed")) {
                        content.style.maxHeight = "";
                        content.style.overflow = "visible";
                    }
                }, { once: true });
            });
        } else {
            // Collapse
            const currentHeight = content.scrollHeight;
            content.style.maxHeight = `${currentHeight}px`;
            content.style.overflow = "hidden";

            requestAnimationFrame(() => {
                content.style.maxHeight = "0px";
                content.style.opacity = "0";
                content.style.paddingTop = "0";
                content.style.paddingBottom = "0";
                content.classList.add("collapsed");
            });
        }
    }
}

/**
 * Exports singleton instances of the UI component classes for easy import and use elsewhere.
 * This allows any part of the application to access the same instance of ModalManager and UIPatterns,
 * ensuring a single source of truth for UI component management.
 */
export const modalManager = new ModalManager();
export const uiPatterns = new UIPatterns();

