import AppData from "./AppData";
import FuseSearch from "../Utils/FuseSearch";
import EventBus from "../Events/EventBus";
import Events from "../Events/Events";

let instance;
const instanceKey = 'product_data_392994';

class ProductData {
    _products = [];
    _categories = [];
    _tags = [];
    _attributes = [];
    _fuseSearch = null;
    _isLoaded = false;

    constructor(key) {
        if (key !== instanceKey) {
            throw new Error('Cannot instantiate like this');
        }
    }

    async load() {
        try {
            const appData = AppData.getInstance();
            const productUrl = appData._product_url;

            if (!productUrl) {
                throw new Error('Product URL not available. Make sure AppData.populate() was called first.');
            }

            const response = await fetch(productUrl);
            if (!response.ok) {
                throw new Error(`Failed to load products: ${response.statusText}`);
            }

            const data = await response.json();
            this._products = data.products || data || [];

            // Get Fuse.js configuration from data attributes or use defaults
            const threshold = this._getFuseThreshold();
            const weights = this._getFuseWeights();

            // Initialize Fuse.js with loaded products and custom configuration
            const fuseOptions = { threshold };
            if (weights) {
                fuseOptions.weights = weights;
            }
            this._fuseSearch = new FuseSearch(this._products, fuseOptions);
            this._isLoaded = true;

            // Trigger event that products are loaded
            EventBus.getInstance().triggerEvent(Events.PRODUCTS_LOADED, {
                products: this._products,
                fuseSearch: this._fuseSearch
            });

            return this._products;
        } catch (error) {
            console.error('Error loading products:', error);
            EventBus.getInstance().triggerEvent(Events.PRODUCTS_LOAD_ERROR, { error });
            throw error;
        }
    }

    async loadCategories() {
        try {
            const appData = AppData.getInstance();
            const categoryUrl = appData._category_url;

            if (!categoryUrl) {
                throw new Error('Category URL not available');
            }

            const response = await fetch(categoryUrl);
            if (!response.ok) {
                throw new Error(`Failed to load categories: ${response.statusText}`);
            }

            const data = await response.json();
            this._categories = data.categories || data || [];
            return this._categories;
        } catch (error) {
            console.error('Error loading categories:', error);
            throw error;
        }
    }

    async loadAttributes() {
        try {
            const appData = AppData.getInstance();
            const attributeUrl = appData._attribute_url;

            if (!attributeUrl) {
                throw new Error('Attribute URL not available');
            }

            const response = await fetch(attributeUrl);
            if (!response.ok) {
                throw new Error(`Failed to load attributes: ${response.statusText}`);
            }

            const data = await response.json();
            this._attributes = data.attributes || data || [];
            return this._attributes;
        } catch (error) {
            console.error('Error loading attributes:', error);
            throw error;
        }
    }

    async loadTags() {
        try {
            const appData = AppData.getInstance();
            const tagUrl = appData._tag_url;

            if (!tagUrl) {
                throw new Error('Tag URL not available');
            }

            const response = await fetch(tagUrl);
            if (!response.ok) {
                throw new Error(`Failed to load tags: ${response.statusText}`);
            }

            const data = await response.json();
            this._tags = data.tags || data || [];
            return this._tags;
        } catch (error) {
            console.error('Error loading tags:', error);
            throw error;
        }
    }

    search(query) {
        if (!this._fuseSearch) {
            return this._products;
        }
        return this._fuseSearch.search(query);
    }

    filter(filters) {
        if (!this._fuseSearch) {
            return this._products;
        }
        return this._fuseSearch.complexFilter(filters);
    }

    getProducts() {
        return this._products;
    }

    getCategories() {
        return this._categories;
    }

    getAttributes() {
        return this._attributes;
    }

    isLoaded() {
        return this._isLoaded;
    }

    getFuseSearch() {
        return this._fuseSearch;
    }

    _getFuseThreshold() {
        // Try to get threshold from search filter container data attribute
        const $searchContainer = jQuery('.fuse-search-filter-container');
        if ($searchContainer.length > 0) {
            const threshold = $searchContainer.data('fuse-threshold');
            if (threshold !== undefined && !isNaN(threshold)) {
                return parseFloat(threshold);
            }
        }
        // Default threshold
        return 0.3;
    }

    _getFuseWeights() {
        // Try to get weights from search filter container data attribute
        const $searchContainer = jQuery('.fuse-search-filter-container');
        if ($searchContainer.length > 0) {
            const weightsData = $searchContainer.data('fuse-weights');
            if (weightsData && typeof weightsData === 'object') {
                return weightsData;
            }
        }
        // Return null to use FuseSearch defaults
        return null;
    }

    static getInstance() {
        if (!instance) {
            instance = new ProductData(instanceKey);
        }
        return instance;
    }
}

export default ProductData;
