import { Logger } from '../../core/logger.js';

export class SPARouter {
    constructor(options = {}) {
        this.options = {
            containerSelector: 'main',
            linkSelector: 'a[href^="/"]', // All internal links
            loadingClass: 'spa-loading',
            excludeSelector: '[data-spa="false"], [download], [target="_blank"], [href^="mailto:"], [href^="tel:"], [href^="#"]',
            enableTransitions: true,
            transitionDuration: 100, // Beschleunigt von 300ms auf 100ms
            skeletonTemplate: this.createSkeletonTemplate(),
            ...options
        };
        
        this.container = null;
        this.isLoading = false;
        this.currentUrl = window.location.href;
        this.abortController = null;
        
        // Bind event handlers to preserve context for removal
        this.handleLinkClick = this.handleLinkClick.bind(this);
        this.handlePopState = this.handlePopState.bind(this);
        this.handleFormSubmit = this.handleFormSubmit.bind(this);
        
        this.init();
    }

    static create(options = {}) {
        return new SPARouter(options);
    }

    init() {
        this.container = document.querySelector(this.options.containerSelector);
        
        if (!this.container) {
            Logger.error(`[SPARouter] Container "${this.options.containerSelector}" not found`);
            return;
        }
        
        this.bindEvents();
        this.setupStyles();
        
        // Handle initial page load for history
        this.updateHistoryState(window.location.href, document.title);
        
        Logger.info('[SPARouter] Initialized');
    }

    bindEvents() {
        // Intercept link clicks
        document.addEventListener('click', this.handleLinkClick);
        
        // Handle browser back/forward
        window.addEventListener('popstate', this.handlePopState);
        
        // Handle form submissions that might redirect
        document.addEventListener('submit', this.handleFormSubmit);
    }

    handleLinkClick(event) {
        const link = event.target.closest(this.options.linkSelector);
        
        if (!link) return;
        
        // Check for exclusions
        if (link.matches(this.options.excludeSelector)) return;
        
        // Check for modifier keys (Ctrl, Cmd, etc.)
        if (event.ctrlKey || event.metaKey || event.shiftKey) return;
        
        event.preventDefault();
        
        const href = link.href;
        const title = link.title || link.textContent.trim();
        
        this.navigate(href, title);
    }

    handlePopState(event) {
        const url = window.location.href;
        
        if (url !== this.currentUrl) {
            this.loadContent(url, false); // Don't update history on popstate
        }
    }

    handleFormSubmit(event) {
        const form = event.target;
        
        // Only handle forms that might redirect (non-AJAX forms)
        if (form.hasAttribute('data-spa') && form.getAttribute('data-spa') === 'false') return;
        if (form._moduleInstance) return; // Skip forms with form-handling module
        
        // For now, let forms submit normally
        // Could be enhanced later to handle form submissions via SPA
    }

    async navigate(url, title = '') {
        if (this.isLoading) {
            Logger.warn(`[SPARouter] Already loading, aborting previous request`);
            this.abortController?.abort();
        }
        
        if (url === this.currentUrl) {
            Logger.info(`[SPARouter] Already at ${url}, skipping navigation`);
            return;
        }
        
        Logger.info(`[SPARouter] Navigating to: ${url}`);
        
        try {
            await this.loadContent(url, true, title);
        } catch (error) {
            if (error.name !== 'AbortError') {
                Logger.error('[SPARouter] Navigation failed:', error);
                // Fallback to normal navigation
                window.location.href = url;
            }
        }
    }

    async loadContent(url, updateHistory = true, title = '') {
        // Prevent loading the same URL that's already current
        if (url === this.currentUrl && !updateHistory) {
            return;
        }
        
        if (this.isLoading) {
            this.abortController?.abort();
        }
        
        this.isLoading = true;
        this.abortController = new AbortController();
        
        try {
            // Show loading state
            this.showLoadingState();
            
            // Request only the main content
            const response = await fetch(url, {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                    'X-SPA-Request': 'true', // Signal to backend this is an SPA request
                    'Accept': 'application/json, text/html'
                },
                signal: this.abortController.signal
            });
            
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            // Check content type to determine how to parse response
            const contentType = response.headers.get('content-type');
            let newContent, newTitle;
            
            if (contentType?.includes('application/json')) {
                // Backend sent JSON SPA response
                const jsonData = await response.json();
                newContent = jsonData.html;
                newTitle = jsonData.title || title;
                
                // Update meta tags if provided
                if (jsonData.meta) {
                    this.updateMetaTags(jsonData.meta);
                }
            } else {
                // Backend sent full HTML response - extract content
                const html = await response.text();
                newContent = this.extractMainContent(html);
                newTitle = this.extractTitle(html) || title;
            }
            
            // Update content
            await this.updateContent(newContent, newTitle);
            
            // Update browser history
            if (updateHistory) {
                this.updateHistoryState(url, newTitle);
            }
            
            this.currentUrl = url;
            
            Logger.info(`[SPARouter] Successfully loaded: ${url}`);
            
        } catch (error) {
            if (error.name !== 'AbortError') {
                this.hideLoadingState();
                throw error;
            }
        } finally {
            this.isLoading = false;
            this.abortController = null;
        }
    }

    extractMainContent(html) {
        // Create a temporary DOM to parse the response
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');
        
        const mainElement = doc.querySelector('main');
        
        if (mainElement) {
            return mainElement.innerHTML;
        }
        
        // Fallback: try to find content in common containers
        const fallbackSelectors = ['[role="main"]', '.main-content', '#main', '.content'];
        
        for (const selector of fallbackSelectors) {
            const element = doc.querySelector(selector);
            if (element) {
                Logger.warn(`[SPARouter] Using fallback selector: ${selector}`);
                return element.innerHTML;
            }
        }
        
        // Last resort: use the entire body
        Logger.warn('[SPARouter] No main element found, using entire body');
        return doc.body.innerHTML;
    }

    extractTitle(html) {
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');
        
        const titleElement = doc.querySelector('title');
        return titleElement ? titleElement.textContent.trim() : '';
    }

    async updateContent(newContent, newTitle) {
        // Update page title
        if (newTitle) {
            document.title = newTitle;
        }
        
        // Smooth transition
        if (this.options.enableTransitions) {
            await this.transitionOut();
        }
        
        // Update content
        this.container.innerHTML = newContent;
        
        // Re-initialize modules for new content
        this.reinitializeModules();
        
        // Smooth transition in
        if (this.options.enableTransitions) {
            await this.transitionIn();
        }
        
        this.hideLoadingState();
        
        // Scroll to top
        window.scrollTo({ top: 0, behavior: 'smooth' });
        
        // Trigger custom event
        this.triggerNavigationEvent();
    }

    showLoadingState() {
        document.body.classList.add(this.options.loadingClass);
        
        // Show skeleton loader
        if (this.options.enableTransitions) {
            this.container.classList.add('spa-transitioning-out');
        }
    }

    hideLoadingState() {
        document.body.classList.remove(this.options.loadingClass);
    }

    async transitionOut() {
        return new Promise(resolve => {
            // Verwende schnellere cubic-bezier für snappigere Animation
            this.container.style.transition = `opacity ${this.options.transitionDuration}ms cubic-bezier(0.4, 0, 1, 1)`;
            this.container.style.opacity = '0';
            
            setTimeout(() => {
                resolve();
            }, this.options.transitionDuration);
        });
    }

    async transitionIn() {
        return new Promise(resolve => {
            this.container.style.opacity = '0';
            
            // Reduziere Verzögerung von 50ms auf 10ms
            setTimeout(() => {
                // Verwende schnellere cubic-bezier für snappigere Animation
                this.container.style.transition = `opacity ${this.options.transitionDuration}ms cubic-bezier(0, 0, 0.2, 1)`;
                this.container.style.opacity = '1';
                
                setTimeout(() => {
                    this.container.style.transition = '';
                    this.container.classList.remove('spa-transitioning-out');
                    resolve();
                }, this.options.transitionDuration);
            }, 10); // Von 50ms auf 10ms reduziert
        });
    }

    updateHistoryState(url, title) {
        const state = { url, title, timestamp: Date.now() };
        
        if (url !== window.location.href) {
            history.pushState(state, title, url);
        } else {
            history.replaceState(state, title, url);
        }
    }

    reinitializeModules() {
        // Re-run form auto-enhancement for new content
        if (window.initAutoFormHandling) {
            window.initAutoFormHandling();
        }
        
        // Re-initialize any data-module elements in new content
        const moduleElements = this.container.querySelectorAll('[data-module]');
        
        moduleElements.forEach(element => {
            const moduleName = element.dataset.module;
            Logger.info(`[SPARouter] Re-initializing module "${moduleName}" on new content`);
            
            // Trigger module initialization (would need access to module system)
            const event = new CustomEvent('spa:reinit-module', {
                detail: { element, moduleName },
                bubbles: true
            });
            element.dispatchEvent(event);
        });
    }

    createSkeletonTemplate() {
        return `
            <div class="spa-skeleton">
                <div class="spa-skeleton-header"></div>
                <div class="spa-skeleton-content">
                    <div class="spa-skeleton-line"></div>
                    <div class="spa-skeleton-line"></div>
                    <div class="spa-skeleton-line short"></div>
                </div>
            </div>
        `;
    }

    setupStyles() {
        if (document.getElementById('spa-router-styles')) return;
        
        const styles = document.createElement('style');
        styles.id = 'spa-router-styles';
        styles.textContent = `
            /* SPA Router Transitions */
            .spa-loading {
                cursor: progress;
            }
            
            .spa-transitioning-out {
                pointer-events: none;
            }
            
            /* Skeleton Loading Styles */
            .spa-skeleton {
                animation: spa-pulse 1.5s ease-in-out infinite alternate;
            }
            
            .spa-skeleton-header {
                height: 2rem;
                background: #e5e7eb;
                border-radius: 0.375rem;
                margin-bottom: 1rem;
                width: 60%;
            }
            
            .spa-skeleton-content {
                space-y: 0.75rem;
            }
            
            .spa-skeleton-line {
                height: 1rem;
                background: #e5e7eb;
                border-radius: 0.375rem;
                margin-bottom: 0.75rem;
            }
            
            .spa-skeleton-line.short {
                width: 75%;
            }
            
            @keyframes spa-pulse {
                0% {
                    opacity: 1;
                }
                100% {
                    opacity: 0.4;
                }
            }
            
            /* Dark mode support */
            @media (prefers-color-scheme: dark) {
                .spa-skeleton-header,
                .spa-skeleton-line {
                    background: #374151;
                }
            }
        `;
        
        document.head.appendChild(styles);
    }

    updateMetaTags(metaData) {
        // Update meta description
        if (metaData.description) {
            let metaDesc = document.querySelector('meta[name="description"]');
            if (metaDesc) {
                metaDesc.content = metaData.description;
            } else {
                metaDesc = document.createElement('meta');
                metaDesc.name = 'description';
                metaDesc.content = metaData.description;
                document.head.appendChild(metaDesc);
            }
        }
        
        // Add other meta tag updates as needed
        Object.entries(metaData).forEach(([key, value]) => {
            if (key !== 'description' && value) {
                let metaTag = document.querySelector(`meta[name="${key}"]`);
                if (metaTag) {
                    metaTag.content = value;
                } else {
                    metaTag = document.createElement('meta');
                    metaTag.name = key;
                    metaTag.content = value;
                    document.head.appendChild(metaTag);
                }
            }
        });
    }

    triggerNavigationEvent() {
        const event = new CustomEvent('spa:navigated', {
            detail: {
                url: this.currentUrl,
                container: this.container,
                timestamp: Date.now()
            },
            bubbles: true
        });
        
        document.dispatchEvent(event);
    }

    // Public API
    navigateTo(url, title) {
        return this.navigate(url, title);
    }

    getCurrentUrl() {
        return this.currentUrl;
    }

    isNavigating() {
        return this.isLoading;
    }

    destroy() {
        this.abortController?.abort();
        
        // Remove event listeners
        document.removeEventListener('click', this.handleLinkClick);
        window.removeEventListener('popstate', this.handlePopState);
        document.removeEventListener('submit', this.handleFormSubmit);
        
        // Remove styles
        const styles = document.getElementById('spa-router-styles');
        if (styles) {
            styles.remove();
        }
        
        Logger.info('[SPARouter] Destroyed');
    }
}