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

export class FormHandler {
    constructor(form, options = {}) {
        this.form = form;
        this.options = {
            validateOnSubmit: true,
            validateOnBlur: false,
            validateOnInput: false,
            showInlineErrors: true,
            preventSubmitOnError: true,
            submitMethod: 'POST',
            ajaxSubmit: true,
            ...options
        };
        
        this.validator = FormValidator.create(form);
        this.state = FormState.create(form);
        this.isSubmitting = false;
        
        this.init();
    }

    static create(form, options = {}) {
        return new FormHandler(form, options);
    }

    init() {
        this.bindEvents();
        this.setupErrorDisplay();
        
        // Mark form as enhanced
        this.form.setAttribute('data-enhanced', 'true');
        
        Logger.info(`[FormHandler] Initialized for form: ${this.form.id || 'unnamed'}`);
    }

    bindEvents() {
        // Submit event
        this.form.addEventListener('submit', (e) => this.handleSubmit(e));
        
        // Field validation events
        if (this.options.validateOnBlur || this.options.validateOnInput) {
            const fields = this.form.querySelectorAll('input, textarea, select');
            
            fields.forEach(field => {
                if (this.options.validateOnBlur) {
                    field.addEventListener('blur', () => this.validateSingleField(field));
                }
                
                if (this.options.validateOnInput) {
                    field.addEventListener('input', () => this.validateSingleField(field));
                }
            });
        }
    }

    async handleSubmit(event) {
        if (this.isSubmitting) {
            event.preventDefault();
            return;
        }

        // Validate if enabled
        if (this.options.validateOnSubmit) {
            const isValid = this.validator.validate();
            
            if (!isValid) {
                event.preventDefault();
                this.displayErrors();
                return;
            }
        }

        // AJAX submission
        if (this.options.ajaxSubmit) {
            event.preventDefault();
            await this.submitViaAjax();
        }
        
        // If not AJAX, let the form submit naturally
    }

    async submitViaAjax() {
        try {
            this.setSubmitState(true);
            this.clearErrors();
            
            const formData = new FormData(this.form);
            const url = this.form.action || window.location.href;
            const method = this.form.method || this.options.submitMethod;
            
            const response = await fetch(url, {
                method: method.toUpperCase(),
                body: formData,
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                }
            });
            
            const data = await this.parseResponse(response);
            
            if (response.ok) {
                this.handleSuccess(data);
            } else {
                this.handleError(data);
            }
            
        } catch (error) {
            Logger.error('[FormHandler] Submit error:', error);
            this.handleError({
                message: 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.',
                errors: {}
            });
        } finally {
            this.setSubmitState(false);
        }
    }

    async parseResponse(response) {
        const contentType = response.headers.get('content-type');
        
        if (contentType?.includes('application/json')) {
            return await response.json();
        }
        
        const text = await response.text();
        
        // Try to parse as JSON, fallback to text
        try {
            return JSON.parse(text);
        } catch {
            return { message: text };
        }
    }

    handleSuccess(data) {
        Logger.info('[FormHandler] Form submitted successfully');
        
        // Clear form if configured
        if (data.clearForm !== false) {
            this.form.reset();
            this.state.reset();
        }
        
        this.showMessage(data.message || 'Formular erfolgreich gesendet!', 'success');
        
        // Call success callback
        this.triggerEvent('form:success', { data });
    }

    handleError(data) {
        Logger.warn('[FormHandler] Form submission error:', data);
        
        // Handle field-specific errors
        if (data.errors && typeof data.errors === 'object') {
            for (const [fieldName, errorMessage] of Object.entries(data.errors)) {
                this.validator.errors.set(fieldName, errorMessage);
            }
            this.displayErrors();
        }
        
        // Show general error message
        this.showMessage(data.message || 'Ein Fehler ist aufgetreten.', 'error');
        
        // Call error callback
        this.triggerEvent('form:error', { data });
    }

    validateSingleField(field) {
        this.validator.errors.delete(field.name);
        this.validator.validateField(field);
        
        this.displayFieldError(field);
    }

    displayErrors() {
        if (!this.options.showInlineErrors) return;
        
        const errors = this.validator.getErrors();
        
        for (const [fieldName, message] of Object.entries(errors)) {
            const field = this.form.querySelector(`[name="${fieldName}"]`);
            if (field) {
                this.displayFieldError(field, message);
            }
        }
    }

    displayFieldError(field, message = null) {
        const errorMessage = message || this.validator.getFieldError(field.name);
        const errorElement = this.getOrCreateErrorElement(field);
        
        if (errorMessage) {
            errorElement.textContent = errorMessage;
            errorElement.style.display = 'block';
            field.classList.add('error');
            field.setAttribute('aria-invalid', 'true');
            field.setAttribute('aria-describedby', errorElement.id);
        } else {
            errorElement.textContent = '';
            errorElement.style.display = 'none';
            field.classList.remove('error');
            field.removeAttribute('aria-invalid');
            field.removeAttribute('aria-describedby');
        }
    }

    getOrCreateErrorElement(field) {
        const errorId = `error-${field.name}`;
        let errorElement = document.getElementById(errorId);
        
        if (!errorElement) {
            errorElement = document.createElement('div');
            errorElement.id = errorId;
            errorElement.className = 'form-error';
            errorElement.setAttribute('role', 'alert');
            errorElement.style.display = 'none';
            
            // Insert after field or field container
            const container = field.closest('.form-group') || field.parentElement;
            container.appendChild(errorElement);
        }
        
        return errorElement;
    }

    setupErrorDisplay() {
        // Add CSS for error states if not present
        if (!document.getElementById('form-handler-styles')) {
            const styles = document.createElement('style');
            styles.id = 'form-handler-styles';
            styles.textContent = `
                .form-error {
                    color: #dc2626;
                    font-size: 0.875rem;
                    margin-top: 0.25rem;
                }
                input.error, textarea.error, select.error {
                    border-color: #dc2626;
                    box-shadow: 0 0 0 1px #dc2626;
                }
                .form-message {
                    padding: 0.75rem;
                    border-radius: 0.375rem;
                    margin: 1rem 0;
                }
                .form-message.success {
                    background-color: #dcfce7;
                    color: #166534;
                    border: 1px solid #bbf7d0;
                }
                .form-message.error {
                    background-color: #fef2f2;
                    color: #dc2626;
                    border: 1px solid #fecaca;
                }
            `;
            document.head.appendChild(styles);
        }
    }

    showMessage(message, type = 'info') {
        let messageContainer = this.form.querySelector('.form-messages');
        
        if (!messageContainer) {
            messageContainer = document.createElement('div');
            messageContainer.className = 'form-messages';
            this.form.prepend(messageContainer);
        }
        
        const messageElement = document.createElement('div');
        messageElement.className = `form-message ${type}`;
        messageElement.textContent = message;
        messageElement.setAttribute('role', type === 'error' ? 'alert' : 'status');
        
        messageContainer.innerHTML = '';
        messageContainer.appendChild(messageElement);
        
        // Auto-hide success messages after 5 seconds
        if (type === 'success') {
            setTimeout(() => {
                if (messageElement.parentElement) {
                    messageElement.remove();
                }
            }, 5000);
        }
    }

    clearErrors() {
        this.validator.clearErrors();
        
        // Clear visual error states
        const errorFields = this.form.querySelectorAll('.error');
        errorFields.forEach(field => {
            field.classList.remove('error');
            field.removeAttribute('aria-invalid');
            field.removeAttribute('aria-describedby');
        });
        
        // Hide error messages
        const errorElements = this.form.querySelectorAll('.form-error');
        errorElements.forEach(element => {
            element.style.display = 'none';
            element.textContent = '';
        });
        
        // Clear general messages
        const messageContainer = this.form.querySelector('.form-messages');
        if (messageContainer) {
            messageContainer.innerHTML = '';
        }
    }

    setSubmitState(isSubmitting) {
        this.isSubmitting = isSubmitting;
        
        const submitButtons = this.form.querySelectorAll('button[type="submit"], input[type="submit"]');
        
        submitButtons.forEach(button => {
            button.disabled = isSubmitting;
            
            if (isSubmitting) {
                button.setAttribute('data-original-text', button.textContent);
                button.textContent = 'Wird gesendet...';
            } else {
                const originalText = button.getAttribute('data-original-text');
                if (originalText) {
                    button.textContent = originalText;
                    button.removeAttribute('data-original-text');
                }
            }
        });
    }

    triggerEvent(eventName, detail = {}) {
        const event = new CustomEvent(eventName, { 
            detail,
            bubbles: true,
            cancelable: true 
        });
        
        this.form.dispatchEvent(event);
    }

    destroy() {
        // Remove event listeners and clean up
        this.form.removeAttribute('data-enhanced');
        Logger.info('[FormHandler] Destroyed');
    }
}