/**
 * Form Validation
 * Client-side form validation for all forms
 */

// ============================================
// Validation Rules
// ============================================

const ValidationRules = {
    required: (value) => value !== null && value !== undefined && value.toString().trim() !== '',
    
    email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
    
    mobile: (value) => /^[6-9]\d{9}$/.test(value),
    
    minLength: (value, min) => value && value.length >= min,
    
    maxLength: (value, max) => value && value.length <= max,
    
    between: (value, min, max) => value && value.length >= min && value.length <= max,
    
    numeric: (value) => /^\d+$/.test(value),
    
    decimal: (value) => /^\d+(\.\d+)?$/.test(value),
    
    alpha: (value) => /^[a-zA-Z]+$/.test(value),
    
    alphanumeric: (value) => /^[a-zA-Z0-9]+$/.test(value),
    
    date: (value) => /^\d{4}-\d{2}-\d{2}$/.test(value) && !isNaN(new Date(value).getTime()),
    
    age: (value) => {
        const age = parseInt(value);
        return !isNaN(age) && age >= 0 && age <= 120;
    },
    
    match: (value, matchValue) => value === matchValue,
    
    unique: async (value, table, column, excludeId = null) => {
        try {
            const response = await fetch(`api/check-unique.php?table=${table}&column=${column}&value=${encodeURIComponent(value)}&exclude=${excludeId || ''}`);
            const data = await response.json();
            return data.unique;
        } catch (error) {
            return true;
        }
    }
};

// ============================================
// Validator Class
// ============================================

class FormValidator {
    constructor(formId, options = {}) {
        this.form = document.getElementById(formId);
        this.options = {
            validateOnBlur: true,
            validateOnInput: false,
            showErrorsInline: true,
            ...options
        };
        this.fields = new Map();
        this.init();
    }
    
    init() {
        if (!this.form) return;
        
        this.scanFields();
        this.bindEvents();
        this.createErrorContainer();
    }
    
    scanFields() {
        const inputs = this.form.querySelectorAll('[data-validate]');
        inputs.forEach(input => {
            const rules = input.dataset.validate.split('|');
            const fieldName = input.name || input.id;
            this.fields.set(fieldName, {
                element: input,
                rules: rules.map(rule => this.parseRule(rule)),
                errors: []
            });
        });
    }
    
    parseRule(rule) {
        const parts = rule.split(':');
        const ruleName = parts[0];
        const params = parts[1] ? parts[1].split(',') : [];
        return { name: ruleName, params: params };
    }
    
    bindEvents() {
        if (this.options.validateOnBlur) {
            this.fields.forEach(field => {
                field.element.addEventListener('blur', () => this.validateField(field.element.name));
            });
        }
        
        if (this.options.validateOnInput) {
            this.fields.forEach(field => {
                field.element.addEventListener('input', () => this.validateField(field.element.name));
            });
        }
        
        this.form.addEventListener('submit', (e) => {
            if (!this.validateForm()) {
                e.preventDefault();
                this.scrollToFirstError();
            }
        });
    }
    
    createErrorContainer() {
        this.fields.forEach(field => {
            if (this.options.showErrorsInline) {
                const errorDiv = document.createElement('div');
                errorDiv.className = 'field-error text-danger small mt-1';
                errorDiv.id = `${field.element.id || field.element.name}_error`;
                field.element.parentNode.insertBefore(errorDiv, field.element.nextSibling);
            }
        });
    }
    
    async validateField(fieldName) {
        const field = this.fields.get(fieldName);
        if (!field) return true;
        
        const value = field.element.value;
        const errors = [];
        
        for (const rule of field.rules) {
            const isValid = await this.applyRule(rule, value, field.element);
            if (!isValid) {
                errors.push(this.getErrorMessage(rule.name, rule.params, field.element));
            }
        }
        
        field.errors = errors;
        this.updateFieldUI(fieldName);
        
        return errors.length === 0;
    }
    
    async applyRule(rule, value, element) {
        const ruleFn = ValidationRules[rule.name];
        if (!ruleFn) return true;
        
        if (ruleFn.constructor.name === 'AsyncFunction') {
            return await ruleFn(value, ...rule.params);
        }
        
        return ruleFn(value, ...rule.params);
    }
    
    getErrorMessage(ruleName, params, element) {
        const customMessage = element.dataset[`msg_${ruleName}`];
        if (customMessage) return customMessage;
        
        const fieldLabel = element.dataset.label || element.placeholder || element.name;
        
        const messages = {
            required: `${fieldLabel} is required`,
            email: `Please enter a valid email address`,
            mobile: `Please enter a valid 10-digit mobile number`,
            minLength: `${fieldLabel} must be at least ${params[0]} characters`,
            maxLength: `${fieldLabel} must not exceed ${params[0]} characters`,
            between: `${fieldLabel} must be between ${params[0]} and ${params[1]} characters`,
            numeric: `${fieldLabel} must contain only numbers`,
            decimal: `${fieldLabel} must be a valid number`,
            alpha: `${fieldLabel} must contain only letters`,
            alphanumeric: `${fieldLabel} must contain only letters and numbers`,
            date: `Please enter a valid date`,
            age: `Please enter a valid age (0-120)`,
            match: `Values do not match`
        };
        
        return messages[ruleName] || `Invalid ${fieldLabel}`;
    }
    
    updateFieldUI(fieldName) {
        const field = this.fields.get(fieldName);
        if (!field) return;
        
        const errorContainer = document.getElementById(`${field.element.id || fieldName}_error`);
        
        if (field.errors.length > 0) {
            field.element.classList.add('is-invalid');
            field.element.classList.remove('is-valid');
            if (errorContainer) {
                errorContainer.innerHTML = field.errors.join('<br>');
            }
        } else {
            field.element.classList.remove('is-invalid');
            if (field.element.value) {
                field.element.classList.add('is-valid');
            }
            if (errorContainer) {
                errorContainer.innerHTML = '';
            }
        }
    }
    
    async validateForm() {
        let isValid = true;
        
        for (const fieldName of this.fields.keys()) {
            const fieldValid = await this.validateField(fieldName);
            if (!fieldValid) isValid = false;
        }
        
        return isValid;
    }
    
    scrollToFirstError() {
        const firstError = this.form.querySelector('.is-invalid');
        if (firstError) {
            firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
            firstError.focus();
        }
    }
    
    reset() {
        this.fields.forEach((field, fieldName) => {
            field.element.value = '';
            field.errors = [];
            field.element.classList.remove('is-valid', 'is-invalid');
            const errorContainer = document.getElementById(`${field.element.id || fieldName}_error`);
            if (errorContainer) errorContainer.innerHTML = '';
        });
    }
}

// ============================================
// Initialize Validators
// ============================================

const validators = {};

function initFormValidator(formId, options = {}) {
    if (document.getElementById(formId)) {
        validators[formId] = new FormValidator(formId, options);
        return validators[formId];
    }
    return null;
}

document.addEventListener('DOMContentLoaded', () => {
    // Initialize validators for common forms
    initFormValidator('loginForm');
    initFormValidator('registerForm');
    initFormValidator('profileForm');
    initFormValidator('passwordForm');
    initFormValidator('caseForm');
    initFormValidator('remedyForm');
    initFormValidator('rubricForm');
    initFormValidator('subscriptionForm');
});

// Export validators for global use
window.FormValidator = FormValidator;
window.initFormValidator = initFormValidator;
window.validators = validators;