/**
 * InsertrAuth - Authentication and state management
 * Pure business logic - no DOM manipulation or UI concerns
 * 
 * Responsibilities:
 * - Manage authentication state
 * - Handle OAuth flows
 * - Validate permissions
 * - Emit state change events
 */
export class InsertrAuth {
    constructor(options = {}) {
        this.options = {
            authProvider: options.authProvider || 'mock',
            mockAuth: options.mockAuth !== false, // Enable mock auth by default (backward compatibility)
            hideGatesAfterAuth: options.hideGatesAfterAuth === true, // Keep gates visible by default
            ...options
        };
        
        // Set mockAuth based on authProvider if not explicitly set
        if (options.authProvider && !options.hasOwnProperty('mockAuth')) {
            this.options.mockAuth = options.authProvider === 'mock';
        }

        // Authentication state
        this.state = {
            isAuthenticated: false,
            editMode: false,
            currentUser: null,
            activeEditor: null,
            isInitialized: false,
            isAuthenticating: false
        };

        // Event listeners for state changes
        this.listeners = {
            stateChange: [],
            authChange: [],
            editModeChange: []
        };
    }

    /**
     * Event emitter methods
     */
    on(event, callback) {
        if (this.listeners[event]) {
            this.listeners[event].push(callback);
        }
    }

    off(event, callback) {
        if (this.listeners[event]) {
            this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
        }
    }

    emit(event, data) {
        if (this.listeners[event]) {
            this.listeners[event].forEach(callback => callback(data));
        }
    }

    /**
     * Initialize gate system (called on page load)
     */
    init() {
        console.log('🔧 Insertr: Scanning for editor gates');
        this.setupEditorGates();
    }

    /**
     * Initialize full editing system (called after successful OAuth)
     */
    initializeFullSystem() {
        if (this.state.isInitialized) {
            return; // Already initialized
        }

        console.log('🔐 Initializing Insertr Editing System');
        
        // Auto-enable edit mode after OAuth
        this.state.editMode = true;
        this.state.isInitialized = true;
        
        // Start the editor system
        if (window.Insertr && window.Insertr.startEditor) {
            window.Insertr.startEditor();
        }
        
        // Emit state change for UI to update
        this.emitStateChange();
        
        console.log('📱 Editing system active');
        console.log('✏️ Edit mode enabled - Click elements to edit');
    }

    /**
     * Setup editor gate click handlers for any .insertr-gate elements
     */
    setupEditorGates() {
        const gates = document.querySelectorAll('.insertr-gate');
        
        if (gates.length === 0) {
            console.log('ℹ️  No .insertr-gate elements found - editor access disabled');
            return;
        }

        console.log(`🚪 Found ${gates.length} editor gate(s)`);
        
        gates.forEach((gate, index) => {
            // Store original text for later restoration
            if (!gate.hasAttribute('data-original-text')) {
                gate.setAttribute('data-original-text', gate.textContent);
            }
            
            gate.addEventListener('click', (e) => {
                e.preventDefault();
                this.handleGateClick(gate, index);
            });
            
            // Add minimal styling to indicate it's clickable
            gate.style.cursor = 'pointer';
        });
    }

    /**
     * Handle click on an editor gate element
     */
    async handleGateClick(gateElement, gateIndex) {
        // Prevent multiple simultaneous authentication attempts
        if (this.state.isAuthenticating) {
            console.log('⏳ Authentication already in progress...');
            return;
        }

        console.log(`🚀 Editor gate activated (gate ${gateIndex + 1})`);
        this.state.isAuthenticating = true;
        
        // Store original text and show loading state
        const originalText = gateElement.textContent;
        gateElement.setAttribute('data-original-text', originalText);
        gateElement.textContent = '⏳ Signing in...';
        gateElement.style.pointerEvents = 'none';
        
        try {
            // Perform OAuth authentication
            await this.performOAuthFlow();
            
            // Initialize full editing system
            this.initializeFullSystem();
            
            // Handle gate visibility based on options
            if (this.options.hideGatesAfterAuth) {
                this.hideAllGates();
            } else {
                this.updateGateState();
            }
            
        } catch (error) {
            console.error('❌ Authentication failed:', error);
            
            // Restore clicked gate to original state
            const originalText = gateElement.getAttribute('data-original-text');
            if (originalText) {
                gateElement.textContent = originalText;
            }
            gateElement.style.pointerEvents = '';
        } finally {
            this.state.isAuthenticating = false;
        }
    }

    /**
     * Perform OAuth authentication flow
     */
    async performOAuthFlow() {
        // Handle different authentication providers
        if (this.options.authProvider === 'mock' || this.options.mockAuth) {
            return this.performMockAuth();
        } else if (this.options.authProvider === 'authentik') {
            return this.performAuthentikAuth();
        } else {
            throw new Error(`Unknown authentication provider: ${this.options.authProvider}`);
        }
    }

    /**
     * Perform mock authentication (development)
     */
    async performMockAuth() {
        console.log('🔐 Mock OAuth: Simulating authentication...');
        
        // Simulate network delay
        await new Promise(resolve => setTimeout(resolve, 1000));
        
        // Set authenticated state
        this.state.isAuthenticated = true;
        this.state.currentUser = {
            name: 'Site Owner',
            email: 'owner@example.com',
            role: 'admin',
            provider: 'mock'
        };
        
        console.log('✅ Mock OAuth: Authentication successful');
    }

    /**
     * Perform Authentik OIDC authentication
     */
    async performAuthentikAuth() {
        console.log('🔐 Starting Authentik OIDC authentication...');
        
        try {
            // Step 1: Initiate OAuth flow with backend
            const response = await fetch('/auth/login', {
                method: 'GET',
                headers: {
                    'Accept': 'application/json'
                }
            });
            
            if (!response.ok) {
                throw new Error(`Failed to initiate OAuth: ${response.status} ${response.statusText}`);
            }
            
            const data = await response.json();
            
            if (!data.redirect_url) {
                throw new Error('No redirect URL returned from server');
            }
            
            console.log('🔄 Redirecting to Authentik for authentication...');
            
            // Step 2: Redirect to Authentik for authentication
            // We'll use a popup window to avoid losing the current page state
            return new Promise((resolve, reject) => {
                const authWindow = window.open(
                    data.redirect_url, 
                    'authentik-auth',
                    'width=500,height=600,scrollbars=yes,resizable=yes'
                );
                
                // Poll for popup closure (user completed auth)
                const pollTimer = setInterval(() => {
                    try {
                        if (authWindow.closed) {
                            clearInterval(pollTimer);
                            // Try to get token from callback
                            this.handleAuthCallback().then(resolve).catch(reject);
                        }
                    } catch (error) {
                        clearInterval(pollTimer);
                        reject(error);
                    }
                }, 1000);
                
                // Timeout after 10 minutes
                setTimeout(() => {
                    clearInterval(pollTimer);
                    if (!authWindow.closed) {
                        authWindow.close();
                    }
                    reject(new Error('Authentication timeout'));
                }, 600000);
            });
            
        } catch (error) {
            console.error('❌ Authentik authentication failed:', error);
            throw error;
        }
    }

    /**
     * Handle OAuth callback (extract token from URL or make callback request)
     */
    async handleAuthCallback() {
        // In a real implementation, this would either:
        // 1. Extract token from URL if using implicit flow
        // 2. Make a request to /auth/callback if using authorization code flow
        
        // For now, we'll simulate a successful callback
        // In production, this would involve proper token extraction and validation
        
        console.log('🔄 Processing authentication callback...');
        
        // Simulate token validation
        await new Promise(resolve => setTimeout(resolve, 500));
        
        // Set authenticated state (in production, extract user info from JWT)
        this.state.isAuthenticated = true;
        this.state.currentUser = {
            name: 'Authentik User',
            email: 'user@example.com',
            role: 'editor',
            provider: 'authentik'
        };
        
        console.log('✅ Authentik OAuth: Authentication successful');
    }

    /**
     * Hide all editor gates after successful authentication (optional)
     */
    hideAllGates() {
        document.body.classList.add('insertr-hide-gates');
        console.log('🚪 Editor gates hidden (hideGatesAfterAuth enabled)');
    }

    /**
     * Update gate state after authentication (restore normal appearance)
     */
    updateGateState() {
        const gates = document.querySelectorAll('.insertr-gate');
        gates.forEach(gate => {
            // Restore original text if it was saved
            const originalText = gate.getAttribute('data-original-text');
            if (originalText) {
                gate.textContent = originalText;
            }
            
            // Restore interactive state
            gate.style.pointerEvents = '';
            gate.style.opacity = '';
        });
        
        console.log('🚪 Editor gates restored to original state');
    }

    /**
     * Toggle authentication state
     */
    toggleAuthentication() {
        this.state.isAuthenticated = !this.state.isAuthenticated;
        this.state.currentUser = this.state.isAuthenticated ? { 
            name: 'Demo User', 
            email: 'demo@example.com',
            role: 'editor'
        } : null;

        // Reset edit mode when logging out
        if (!this.state.isAuthenticated) {
            this.state.editMode = false;
        }

        this.emitStateChange();

        console.log(this.state.isAuthenticated 
            ? '✅ Authenticated as Demo User' 
            : '❌ Logged out');
    }

    /**
     * Toggle edit mode (only when authenticated)
     */
    toggleEditMode() {
        if (!this.state.isAuthenticated) {
            console.warn('❌ Cannot enable edit mode - not authenticated');
            return;
        }

        this.state.editMode = !this.state.editMode;

        // Cancel any active editing when turning off edit mode
        if (!this.state.editMode && this.state.activeEditor) {
            // This would be handled by the main editor
            this.state.activeEditor = null;
        }

        this.emitStateChange();

        console.log(this.state.editMode 
            ? '✏️ Edit mode ON - Click elements to edit' 
            : '👀 Edit mode OFF - Read-only view');
    }

    /**
     * Emit state change events for UI updates
     */
    emitStateChange() {
        const stateData = {
            isAuthenticated: this.state.isAuthenticated,
            editMode: this.state.editMode,
            currentUser: this.state.currentUser
        };

        this.emit('stateChange', stateData);
        this.emit('authChange', { isAuthenticated: this.state.isAuthenticated, user: this.state.currentUser });
        this.emit('editModeChange', { editMode: this.state.editMode });
    }

    /**
     * Check if user is authenticated
     */
    isAuthenticated() {
        return this.state.isAuthenticated;
    }

    /**
     * Check if edit mode is enabled
     */
    isEditMode() {
        return this.state.editMode;
    }

    /**
     * Get current user info
     */
    getCurrentUser() {
        return this.state.currentUser;
    }



    /**
     * Get authentication state snapshot
     */
    getState() {
        return {
            isAuthenticated: this.state.isAuthenticated,
            editMode: this.state.editMode,
            currentUser: this.state.currentUser,
            isInitialized: this.state.isInitialized,
            isAuthenticating: this.state.isAuthenticating
        };
    }
}