import EventBus from "../Events/EventBus";
import Events from "../Events/Events";
import ProductData from "../Common/ProductData";
import URLStateManager from "../Utils/URLStateManager";
import MobileFiltersUI from "./Filters/MobileFiltersUI";
import Storage from "../Utils/Storage";

class FilterManager {
    _activeFilters = {
        categories: [],
        tags: [],
        attributes: {},
        query: '',
        priceRange: null
    };
    _isRestoringFromURL = false;
    _productsLoaded = false;
    _filteredProducts = [];

    init() {
        this._listenToEvents();
        this._listenToPopState();
    }

    _listenToEvents() {
        const eventBus = EventBus.getInstance();

        // Listen for products loaded - then restore from URL if needed
        eventBus.registerDynamicEvent({
            key: Events.PRODUCTS_LOADED,
            callback: () => this._handleProductsLoaded()
        });

        // Listen for category selection
        eventBus.registerDynamicEvent({
            key: Events.CATEGORY_SELECTED,
            callback: (payload) => this._handleCategorySelected(payload)
        });

        // Listen for category deselection
        eventBus.registerDynamicEvent({
            key: Events.CATEGORY_DESELECTED,
            callback: (payload) => this._handleCategoryDeselected(payload)
        });

        // Listen for tag selection
        eventBus.registerDynamicEvent({
            key: Events.TAG_SELECTED,
            callback: (payload) => this._handleTagSelected(payload)
        });

        // Listen for tag deselection
        eventBus.registerDynamicEvent({
            key: Events.TAG_DESELECTED,
            callback: (payload) => this._handleTagDeselected(payload)
        });

        // Listen for attribute selection
        eventBus.registerDynamicEvent({
            key: Events.ATTRIBUTE_SELECTED,
            callback: (payload) => this._handleAttributeSelected(payload)
        });

        // Listen for attribute deselection
        eventBus.registerDynamicEvent({
            key: Events.ATTRIBUTE_DESELECTED,
            callback: (payload) => this._handleAttributeDeselected(payload)
        });

        // Listen for search query changes
        eventBus.registerDynamicEvent({
            key: Events.SEARCH_QUERY_CHANGED,
            callback: (payload) => this._handleSearchQueryChanged(payload)
        });

        // Listen for price range changes
        eventBus.registerDynamicEvent({
            key: Events.PRICE_RANGE_CHANGED,
            callback: (payload) => this._handlePriceRangeChanged(payload)
        });

        // Listen for clear filters
        eventBus.registerDynamicEvent({
            key: Events.FILTERS_CLEARED,
            callback: () => this._handleClearFilters()
        });
    }

    _handleCategorySelected(payload) {
        const categoryId = payload?.categoryId;
        if (categoryId && !this._activeFilters.categories.includes(categoryId)) {
            this._activeFilters.categories.push(categoryId);
            this._applyFilters();
        }
    }

    _handleCategoryDeselected(payload) {
        const categoryId = payload?.categoryId;
        if (categoryId) {
            this._activeFilters.categories = this._activeFilters.categories.filter(
                id => id !== categoryId
            );
            this._applyFilters();
        }
    }

    _handleTagSelected(payload) {
        const tagId = payload?.tagId;
        if (tagId && !this._activeFilters.tags.includes(tagId)) {
            this._activeFilters.tags.push(tagId);
            this._applyFilters();
        }
    }

    _handleTagDeselected(payload) {
        const tagId = payload?.tagId;
        if (tagId) {
            this._activeFilters.tags = this._activeFilters.tags.filter(
                id => id !== tagId
            );
            this._applyFilters();
        }
    }

    _handleAttributeSelected(payload) {
        const { attributeKey, attributeValue } = payload || {};
        if (attributeKey && attributeValue) {
            if (!this._activeFilters.attributes[attributeKey]) {
                this._activeFilters.attributes[attributeKey] = [];
            }
            if (!this._activeFilters.attributes[attributeKey].includes(attributeValue)) {
                this._activeFilters.attributes[attributeKey].push(attributeValue);
            }
            this._applyFilters();
        }
    }

    _handleAttributeDeselected(payload) {
        const { attributeKey, attributeValue } = payload || {};
        if (attributeKey && attributeValue && this._activeFilters.attributes[attributeKey]) {
            this._activeFilters.attributes[attributeKey] = this._activeFilters.attributes[attributeKey].filter(
                val => val !== attributeValue
            );
            if (this._activeFilters.attributes[attributeKey].length === 0) {
                delete this._activeFilters.attributes[attributeKey];
            }
            this._applyFilters();
        }
    }

    _handleSearchQueryChanged(payload) {
        this._activeFilters.query = payload?.query || '';
        this._applyFilters();
    }

    _handlePriceRangeChanged(payload) {
        const { min, max } = payload || {};
        if (min !== null || max !== null) {
            this._activeFilters.priceRange = { min, max };
        } else {
            this._activeFilters.priceRange = null;
        }
        this._applyFilters();
    }

    _handleClearFilters() {
        this._activeFilters = {
            categories: [],
            tags: [],
            attributes: {},
            query: '',
            priceRange: null
        };

        // Clear URL parameters
        URLStateManager.clearURL();
        this._filteredProducts = [];

        this._applyFilters();
    }

    _applyFilters() {
        const productData = ProductData.getInstance();
        this._filteredProducts = productData.filter(this._activeFilters);

        // Update URL with current filter state (only if not restoring from URL)
        if (!this._isRestoringFromURL) {
            URLStateManager.updateURL(this._activeFilters);
        }

        Storage.getInstance().setShowingProductsCount(this._filteredProducts.length);
        if (MobileFiltersUI.getInstance().isOpen()) {
            return;
        }

        EventBus.getInstance().triggerEvent(Events.PRODUCTS_FILTERED, {
            products: this._filteredProducts,
            filters: this._activeFilters,
            totalCount: this._filteredProducts.length
        });
    }

    triggerApplyFilters() {

        // Ensure _filteredProducts is up-to-date with current filter state
        const productData = ProductData.getInstance();
        this._filteredProducts = productData.filter(this._activeFilters);

        EventBus.getInstance().triggerEvent(Events.PRODUCTS_FILTERED, {
            products: this._filteredProducts,
            filters: this._activeFilters,
            totalCount: this._filteredProducts.length
        });
    }

    _handleProductsLoaded() {
        this._productsLoaded = true;

        // Restore filters from URL on initial page load
        if (URLStateManager.hasFiltersInURL()) {
            this._restoreFiltersFromURL();
        }
    }

    _listenToPopState() {
        window.addEventListener('popstate', (event) => {
            // Handle browser back/forward navigation
            if (this._productsLoaded) {
                this._restoreFiltersFromURL();
            }
        });
    }

    _restoreFiltersFromURL() {
        if (!URLStateManager.hasFiltersInURL() || !this._productsLoaded) {
            return;
        }

        this._isRestoringFromURL = true;

        const filters = URLStateManager.decodeFilters();
        this._activeFilters = filters;

        // Trigger UI updates
        EventBus.getInstance().triggerEvent(Events.FILTERS_RESTORED_FROM_URL, filters);

        // Apply filters
        this._applyFilters();

        this._isRestoringFromURL = false;
    }

    setFilters(filters) {
        this._activeFilters = { ...filters };
        this._applyFilters();
    }

    getActiveFilters() {
        return { ...this._activeFilters };
    }

    static getInstance() {
        if (!window._filterManagerInstance) {
            window._filterManagerInstance = new FilterManager();
        }
        return window._filterManagerInstance;
    }
}

export default FilterManager;
