/**
 * LoadUsers - System do ładowania użytkowników z API z paginacją, filtrowaniem i sortowaniem
 * Obsługuje duże bazy danych (setki tysięcy użytkowników)
 */

class LoadUsers {
    constructor(apiUrl = '/api/loadUsers.php') {
        this.apiUrl = apiUrl;
        this.currentPage = 1;
        this.limit = 50;
        this.sortBy = 'id';
        this.sortOrder = 'ASC';
        this.filters = {};
        this.cache = {};
    }

    /**
     * Główna metoda pobierająca użytkowników
     * @param {Object} options - Opcje zapytania (page, limit, sortBy, sortOrder, filters)
     * @returns {Promise<Object>} - Obiekt z użytkownikami i informacjami o paginacji
     */
    async getUsers(options = {}) {
        // Aktualizacja parametrów
        if (options.page !== undefined) this.currentPage = options.page;
        if (options.limit !== undefined) this.limit = options.limit;
        if (options.sortBy !== undefined) this.sortBy = options.sortBy;
        if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;
        if (options.filters !== undefined) this.filters = options.filters;

        // Budowanie URL z parametrami
        const url = this.buildUrl();

        // Sprawdzenie cache
        const cacheKey = url;
        if (this.cache[cacheKey]) {
            console.log('Zwracam z cache:', cacheKey);
            return this.cache[cacheKey];
        }

        try {
            const response = await fetch(url);
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const data = await response.json();
            
            if (!data.success) {
                throw new Error(data.error || 'Błąd pobierania użytkowników');
            }

            // Zapisanie do cache
            this.cache[cacheKey] = data;
            
            return data;
        } catch (error) {
            console.error('Błąd podczas pobierania użytkowników:', error);
            throw error;
        }
    }

    /**
     * Buduje URL z parametrami
     * @returns {string} - Pełny URL z parametrami
     */
    buildUrl() {
        const params = new URLSearchParams();
        
        params.append('page', this.currentPage);
        params.append('limit', this.limit);
        params.append('sortBy', this.sortBy);
        params.append('sortOrder', this.sortOrder);
        
        // Dodanie filtrów
        Object.keys(this.filters).forEach(key => {
            if (this.filters[key] !== null && this.filters[key] !== undefined && this.filters[key] !== '') {
                params.append(key, this.filters[key]);
            }
        });
        
        return `${this.apiUrl}?${params.toString()}`;
    }

    /**
     * Przechodzi do następnej strony
     * @returns {Promise<Object>}
     */
    async nextPage() {
        return await this.getUsers({ page: this.currentPage + 1 });
    }

    /**
     * Przechodzi do poprzedniej strony
     * @returns {Promise<Object>}
     */
    async previousPage() {
        if (this.currentPage > 1) {
            return await this.getUsers({ page: this.currentPage - 1 });
        }
        return null;
    }

    /**
     * Przechodzi do konkretnej strony
     * @param {number} page - Numer strony
     * @returns {Promise<Object>}
     */
    async goToPage(page) {
        return await this.getUsers({ page: page });
    }

    /**
     * Ustawia sortowanie
     * @param {string} column - Kolumna do sortowania
     * @param {string} order - Kierunek sortowania (ASC/DESC)
     * @returns {Promise<Object>}
     */
    async sort(column, order = 'ASC') {
        return await this.getUsers({ 
            sortBy: column, 
            sortOrder: order,
            page: 1 // Reset do pierwszej strony przy sortowaniu
        });
    }

    /**
     * Ustawia filtry
     * @param {Object} filters - Obiekt z filtrami
     * @returns {Promise<Object>}
     */
    async filter(filters) {
        return await this.getUsers({ 
            filters: filters,
            page: 1 // Reset do pierwszej strony przy filtrowaniu
        });
    }

    /**
     * Dodaje pojedynczy filtr
     * @param {string} key - Nazwa filtru
     * @param {*} value - Wartość filtru
     * @returns {Promise<Object>}
     */
    async addFilter(key, value) {
        this.filters[key] = value;
        return await this.getUsers({ page: 1 });
    }

    /**
     * Usuwa pojedynczy filtr
     * @param {string} key - Nazwa filtru
     * @returns {Promise<Object>}
     */
    async removeFilter(key) {
        delete this.filters[key];
        return await this.getUsers({ page: 1 });
    }

    /**
     * Czyści wszystkie filtry
     * @returns {Promise<Object>}
     */
    async clearFilters() {
        this.filters = {};
        return await this.getUsers({ page: 1 });
    }

    /**
     * Czyści cache
     */
    clearCache() {
        this.cache = {};
    }

    /**
     * Resetuje wszystkie parametry do domyślnych
     * @returns {Promise<Object>}
     */
    async reset() {
        this.currentPage = 1;
        this.limit = 50;
        this.sortBy = 'id';
        this.sortOrder = 'ASC';
        this.filters = {};
        this.clearCache();
        return await this.getUsers();
    }

    /**
     * Eksportuje aktualny stan jako URL (do bookmarków)
     * @returns {string}
     */
    getShareableUrl() {
        return this.buildUrl();
    }

    /**
     * Wczytuje stan z URL
     * @param {string} url - URL ze stanem
     * @returns {Promise<Object>}
     */
    async loadFromUrl(url) {
        const urlObj = new URL(url);
        const params = new URLSearchParams(urlObj.search);
        
        const options = {};
        
        if (params.has('page')) options.page = parseInt(params.get('page'));
        if (params.has('limit')) options.limit = parseInt(params.get('limit'));
        if (params.has('sortBy')) options.sortBy = params.get('sortBy');
        if (params.has('sortOrder')) options.sortOrder = params.get('sortOrder');
        
        // Wczytanie filtrów
        const filters = {};
        params.forEach((value, key) => {
            if (!['page', 'limit', 'sortBy', 'sortOrder'].includes(key)) {
                filters[key] = value;
            }
        });
        
        if (Object.keys(filters).length > 0) {
            options.filters = filters;
        }
        
        return await this.getUsers(options);
    }
}

// Export dla Node.js / ES Modules
if (typeof module !== 'undefined' && module.exports) {
    module.exports = LoadUsers;
}
