/**
 * LiveComponents - Zero-Dependency Interactive Component System
 * Part of Custom PHP Framework
 */
class LiveComponentManager {
    constructor() {
        this.components = new Map();
        this.pollingIntervals = new Map();
        this.init();
    }

    init() {
        // Find all live components
        document.querySelectorAll('[data-live-component]').forEach(el => {
            const id = el.dataset.liveComponent;
            const state = JSON.parse(el.dataset.componentState || '{}');

            this.components.set(id, {
                element: el,
                state: state
            });

            // Setup event listeners
            this.setupListeners(el, id);
        });
    }

    setupListeners(element, componentId) {
        // Action buttons and links
        element.querySelectorAll('[data-live-action]').forEach(btn => {
            btn.addEventListener('click', async (e) => {
                const action = btn.dataset.liveAction;
                const params = this.getActionParams(btn);

                if (btn.dataset.livePrevent !== undefined) {
                    e.preventDefault();
                }

                await this.callAction(componentId, action, params);
            });
        });

        // Forms with data-live-action
        element.querySelectorAll('form[data-live-action]').forEach(form => {
            form.addEventListener('submit', async (e) => {
                e.preventDefault();

                const action = form.dataset.liveAction;
                const formData = new FormData(form);
                const params = Object.fromEntries(formData);

                await this.callAction(componentId, action, params);
            });
        });

        // Upload forms
        element.querySelectorAll('form[data-live-upload]').forEach(form => {
            form.addEventListener('submit', async (e) => {
                e.preventDefault();

                const action = form.dataset.liveUpload;
                const fileInput = form.querySelector('input[type="file"]');
                const file = fileInput?.files[0];

                if (!file) return;

                // Validate file size
                const maxSize = parseInt(fileInput.dataset.maxSize || '0');
                if (maxSize > 0 && file.size > maxSize) {
                    alert(`File too large. Max ${(maxSize / 1024 / 1024).toFixed(2)}MB`);
                    return;
                }

                await this.uploadFile(componentId, action, file, form);
            });
        });

        // Setup polling if interval is set
        const pollInterval = element.dataset.pollInterval;
        if (pollInterval) {
            this.startPolling(componentId, parseInt(pollInterval));
        }
    }

    async callAction(componentId, method, params = {}) {
        const component = this.components.get(componentId);
        if (!component) return;

        try {
            // URL-encode the component ID to handle special characters (backslashes, colons)
            const encodedId = encodeURIComponent(componentId);

            const response = await fetch(`/live-component/${encodedId}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Requested-With': 'XMLHttpRequest'
                },
                body: JSON.stringify({
                    component_id: componentId,
                    method: method,
                    params: params,
                    state: component.state.data || {}
                })
            });

            if (!response.ok) {
                throw new Error(`HTTP ${response.status}`);
            }

            const data = await response.json();

            // Update DOM
            component.element.innerHTML = data.html;

            // Update state
            if (data.state) {
                component.state = JSON.parse(data.state);
                component.element.dataset.componentState = data.state;
            }

            // Re-setup listeners
            this.setupListeners(component.element, componentId);

            // Dispatch custom events
            data.events?.forEach(event => {
                document.dispatchEvent(new CustomEvent(event.name, {
                    detail: event.data
                }));
            });

        } catch (error) {
            console.error('LiveComponent error:', error);
        }
    }

    async uploadFile(componentId, action, file, form) {
        const component = this.components.get(componentId);
        if (!component) return;

        // Create FormData
        const formData = new FormData();
        formData.append('file', file);
        formData.append('component_id', componentId);
        formData.append('method', action);
        formData.append('state', JSON.stringify(component.state.data || {}));

        try {
            // Show upload progress
            this.updateUploadProgress(componentId, 0);

            const xhr = new XMLHttpRequest();

            // Track upload progress
            xhr.upload.addEventListener('progress', (e) => {
                if (e.lengthComputable) {
                    const percentage = (e.loaded / e.total) * 100;
                    this.updateUploadProgress(componentId, percentage);
                }
            });

            // Handle completion
            xhr.addEventListener('load', () => {
                if (xhr.status === 200) {
                    const data = JSON.parse(xhr.responseText);

                    // Update component
                    component.element.innerHTML = data.html;
                    if (data.state) {
                        component.state = JSON.parse(data.state);
                        component.element.dataset.componentState = data.state;
                    }

                    this.setupListeners(component.element, componentId);
                    this.updateUploadProgress(componentId, 100);

                    // Reset form
                    form.reset();
                } else {
                    alert('Upload failed');
                }
            });

            xhr.addEventListener('error', () => {
                alert('Upload error');
            });

            // URL-encode the component ID to handle special characters
            const encodedId = encodeURIComponent(componentId);
            xhr.open('POST', `/live-component/${encodedId}/upload`);
            xhr.send(formData);

        } catch (error) {
            console.error('Upload error:', error);
            alert('Upload failed');
        }
    }

    updateUploadProgress(componentId, percentage) {
        const component = this.components.get(componentId);
        if (!component) return;

        const progressBar = component.element.querySelector('.progress-bar');
        const progressText = component.element.querySelector('.upload-progress span');

        if (progressBar) {
            progressBar.style.width = `${percentage}%`;
        }
        if (progressText) {
            progressText.textContent = `${Math.round(percentage)}%`;
        }
    }

    startPolling(componentId, interval) {
        // Clear existing interval
        this.stopPolling(componentId);

        // Start new interval
        const intervalId = setInterval(async () => {
            await this.callAction(componentId, 'poll', {});
        }, interval);

        this.pollingIntervals.set(componentId, intervalId);
    }

    stopPolling(componentId) {
        const intervalId = this.pollingIntervals.get(componentId);
        if (intervalId) {
            clearInterval(intervalId);
            this.pollingIntervals.delete(componentId);
        }
    }

    removeComponent(componentId) {
        this.stopPolling(componentId);
        this.components.delete(componentId);
    }

    getActionParams(element) {
        // Extract params from data attributes
        const params = {};

        Object.keys(element.dataset).forEach(key => {
            if (key.startsWith('param')) {
                const paramName = key.replace('param', '').toLowerCase();
                params[paramName] = element.dataset[key];
            }
        });

        return params;
    }

    // Debounce utility
    debounce(func, wait) {
        let timeout;
        return (...args) => {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }
}

// Auto-init with error handling
try {
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            window.liveComponents = new LiveComponentManager();
            console.log('LiveComponentManager initialized (DOMContentLoaded)');
        });
    } else {
        window.liveComponents = new LiveComponentManager();
        console.log('LiveComponentManager initialized (immediate)');
    }
} catch (error) {
    console.error('Failed to initialize LiveComponentManager:', error);
    window.liveComponents = null;
}
