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

export class FormState {
    constructor(form) {
        this.form = form;
        this.pristineValues = new Map();
        this.touchedFields = new Set();
        this.dirtyFields = new Set();
        
        this.init();
    }

    static create(form) {
        return new FormState(form);
    }

    init() {
        // Store initial values
        this.captureInitialValues();
        
        // Track field interactions
        this.bindEvents();
        
        Logger.info(`[FormState] Initialized for form: ${this.form.id || 'unnamed'}`);
    }

    captureInitialValues() {
        const fields = this.form.querySelectorAll('input, textarea, select');
        
        fields.forEach(field => {
            let value;
            
            switch (field.type) {
                case 'checkbox':
                case 'radio':
                    value = field.checked;
                    break;
                default:
                    value = field.value;
            }
            
            this.pristineValues.set(field.name, value);
        });
    }

    bindEvents() {
        const fields = this.form.querySelectorAll('input, textarea, select');
        
        fields.forEach(field => {
            // Skip hidden fields for interaction tracking (they can't be touched/interacted with)
            if (field.type === 'hidden') return;
            
            // Mark field as touched on first interaction
            field.addEventListener('focus', () => {
                this.markAsTouched(field.name);
            });
            
            // Track changes for dirty state
            field.addEventListener('input', () => {
                this.checkDirtyState(field);
            });
            
            field.addEventListener('change', () => {
                this.checkDirtyState(field);
            });
        });
    }

    markAsTouched(fieldName) {
        this.touchedFields.add(fieldName);
        this.updateFormClasses();
    }

    checkDirtyState(field) {
        const fieldName = field.name;
        const currentValue = this.getFieldValue(field);
        const pristineValue = this.pristineValues.get(fieldName);
        
        if (currentValue !== pristineValue) {
            this.dirtyFields.add(fieldName);
        } else {
            this.dirtyFields.delete(fieldName);
        }
        
        this.updateFormClasses();
    }

    getFieldValue(field) {
        switch (field.type) {
            case 'checkbox':
            case 'radio':
                return field.checked;
            default:
                return field.value;
        }
    }

    updateFormClasses() {
        // Update form-level classes based on state
        if (this.isDirty()) {
            this.form.classList.add('form-dirty');
            this.form.classList.remove('form-pristine');
        } else {
            this.form.classList.add('form-pristine');
            this.form.classList.remove('form-dirty');
        }

        if (this.hasTouchedFields()) {
            this.form.classList.add('form-touched');
        } else {
            this.form.classList.remove('form-touched');
        }
    }

    // State check methods
    isPristine() {
        return this.dirtyFields.size === 0;
    }

    isDirty() {
        return this.dirtyFields.size > 0;
    }

    hasTouchedFields() {
        return this.touchedFields.size > 0;
    }

    isFieldTouched(fieldName) {
        return this.touchedFields.has(fieldName);
    }

    isFieldDirty(fieldName) {
        return this.dirtyFields.has(fieldName);
    }

    isFieldPristine(fieldName) {
        return !this.dirtyFields.has(fieldName);
    }

    // Get field states
    getFieldState(fieldName) {
        return {
            pristine: this.isFieldPristine(fieldName),
            dirty: this.isFieldDirty(fieldName),
            touched: this.isFieldTouched(fieldName),
            pristineValue: this.pristineValues.get(fieldName),
            currentValue: this.getCurrentFieldValue(fieldName)
        };
    }

    getCurrentFieldValue(fieldName) {
        const field = this.form.querySelector(`[name="${fieldName}"]`);
        return field ? this.getFieldValue(field) : undefined;
    }

    // Form-level state
    getFormState() {
        return {
            pristine: this.isPristine(),
            dirty: this.isDirty(),
            touched: this.hasTouchedFields(),
            dirtyFields: Array.from(this.dirtyFields),
            touchedFields: Array.from(this.touchedFields),
            totalFields: this.pristineValues.size
        };
    }

    // Reset methods
    reset() {
        this.touchedFields.clear();
        this.dirtyFields.clear();
        
        // Re-capture values after form reset
        setTimeout(() => {
            this.captureInitialValues();
            this.updateFormClasses();
        }, 0);
        
        Logger.info('[FormState] State reset');
    }

    resetField(fieldName) {
        this.touchedFields.delete(fieldName);
        this.dirtyFields.delete(fieldName);
        
        // Reset field to pristine value
        const field = this.form.querySelector(`[name="${fieldName}"]`);
        const pristineValue = this.pristineValues.get(fieldName);
        
        if (field && pristineValue !== undefined) {
            switch (field.type) {
                case 'checkbox':
                case 'radio':
                    field.checked = pristineValue;
                    break;
                default:
                    field.value = pristineValue;
            }
        }
        
        this.updateFormClasses();
        
        Logger.info(`[FormState] Field "${fieldName}" reset to pristine state`);
    }

    // Event handling for external state changes
    triggerStateEvent(eventName, detail = {}) {
        const event = new CustomEvent(eventName, {
            detail: {
                ...detail,
                formState: this.getFormState()
            },
            bubbles: true,
            cancelable: true
        });
        
        this.form.dispatchEvent(event);
    }

    // Utility methods
    hasChanges() {
        return this.isDirty();
    }

    getChangedFields() {
        const changes = {};
        
        this.dirtyFields.forEach(fieldName => {
            changes[fieldName] = {
                pristineValue: this.pristineValues.get(fieldName),
                currentValue: this.getCurrentFieldValue(fieldName)
            };
        });
        
        return changes;
    }

    // Warning for unsaved changes
    enableUnsavedChangesWarning() {
        window.addEventListener('beforeunload', (e) => {
            if (this.isDirty()) {
                e.preventDefault();
                e.returnValue = 'Sie haben ungespeicherte Änderungen. Möchten Sie die Seite wirklich verlassen?';
                return e.returnValue;
            }
        });
    }

    destroy() {
        this.pristineValues.clear();
        this.touchedFields.clear();
        this.dirtyFields.clear();
        
        Logger.info('[FormState] Destroyed');
    }
}