/**
 * International Phone Input Component for SPAI Contact Form
 * Based on backend phone-input.js implementation
 */

window.SPAIPhoneInput = (function() {
    'use strict';
    
    // Default configuration
    const defaultConfig = {
        initialCountry: 'us',
        preferredCountries: ['us', 'ca', 'gb'],
        onValidation: null,
        required: false
    };
    
    // Phone number formatting patterns
    const formatPatterns = {
        'us': { maxLength: 10, format: (v) => formatUSCA(v) },
        'ca': { maxLength: 10, format: (v) => formatUSCA(v) },
        'gb': { maxLength: 11, format: (v) => formatUK(v) },
        'pl': { maxLength: 9, format: (v) => formatDefault(v) },
        'de': { maxLength: 12, format: (v) => formatDefault(v) },
        'fr': { maxLength: 9, format: (v) => formatDefault(v) },
        'it': { maxLength: 10, format: (v) => formatDefault(v) },
        'es': { maxLength: 9, format: (v) => formatDefault(v) },
        'default': { maxLength: 15, format: (v) => formatDefault(v) }
    };
    
    // Country dial codes mapping
    const countryDialCodes = {
        '1': 'us',
        '7': 'ru',
        '20': 'eg',
        '27': 'za',
        '30': 'gr',
        '31': 'nl',
        '32': 'be',
        '33': 'fr',
        '34': 'es',
        '36': 'hu',
        '39': 'it',
        '40': 'ro',
        '41': 'ch',
        '43': 'at',
        '44': 'gb',
        '45': 'dk',
        '46': 'se',
        '47': 'no',
        '48': 'pl',
        '49': 'de',
        '51': 'pe',
        '52': 'mx',
        '53': 'cu',
        '54': 'ar',
        '55': 'br',
        '56': 'cl',
        '57': 'co',
        '58': 've',
        '60': 'my',
        '61': 'au',
        '62': 'id',
        '63': 'ph',
        '64': 'nz',
        '65': 'sg',
        '66': 'th',
        '81': 'jp',
        '82': 'kr',
        '84': 'vn',
        '86': 'cn',
        '90': 'tr',
        '91': 'in',
        '92': 'pk',
        '93': 'af',
        '94': 'lk',
        '95': 'mm',
        '98': 'ir'
    };
    
    // Phone validation rules by country
    const validationRules = {
        'us': { min: 10, max: 10 },
        'ca': { min: 10, max: 10 },
        'gb': { min: 10, max: 11 },
        'de': { min: 10, max: 12 },
        'fr': { min: 9, max: 9 },
        'it': { min: 9, max: 10 },
        'es': { min: 9, max: 9 },
        'au': { min: 9, max: 9 },
        'jp': { min: 10, max: 11 },
        'cn': { min: 11, max: 11 },
        'in': { min: 10, max: 10 },
        'br': { min: 10, max: 11 },
        'mx': { min: 10, max: 10 },
        'ru': { min: 10, max: 10 },
        'kr': { min: 9, max: 11 },
        'za': { min: 9, max: 9 },
        'pl': { min: 9, max: 9 },
        'nl': { min: 9, max: 9 },
        'se': { min: 7, max: 9 },
        'no': { min: 8, max: 8 },
        'fi': { min: 5, max: 12 },
        'dk': { min: 8, max: 8 },
        'ch': { min: 9, max: 9 },
        'at': { min: 10, max: 13 },
        'nz': { min: 8, max: 10 },
        'sg': { min: 8, max: 8 },
        'hk': { min: 8, max: 8 },
        'default': { min: 7, max: 15 }
    };
    
    // Format US/CA numbers as XXX XXX XXXX
    function formatUSCA(value) {
        if (value.length <= 3) {
            return value;
        } else if (value.length <= 6) {
            return `${value.slice(0, 3)} ${value.slice(3)}`;
        } else {
            return `${value.slice(0, 3)} ${value.slice(3, 6)} ${value.slice(6, 10)}`;
        }
    }
    
    // Format UK numbers as XXXX XXX XXXX
    function formatUK(value) {
        if (value.length <= 4) {
            return value;
        } else if (value.length <= 7) {
            return `${value.slice(0, 4)} ${value.slice(4)}`;
        } else {
            return `${value.slice(0, 4)} ${value.slice(4, 7)} ${value.slice(7, 11)}`;
        }
    }
    
    // Format other countries - space every 3 digits
    function formatDefault(value) {
        let chunks = [];
        for (let i = 0; i < value.length; i += 3) {
            chunks.push(value.slice(i, i + 3));
        }
        return chunks.join(' ');
    }
    
    // Initialize a phone input
    function init(selector, options = {}) {
        const config = Object.assign({}, defaultConfig, options);
        const phoneInput = document.querySelector(selector);
        
        if (!phoneInput) {
            console.error('SPAIPhoneInput: Element not found:', selector);
            return null;
        }
        
        // Initialize intl-tel-input
        const iti = window.intlTelInput(phoneInput, {
            initialCountry: config.initialCountry,
            preferredCountries: config.preferredCountries,
            separateDialCode: config.separateDialCode !== false,
            formatOnDisplay: true,
            nationalMode: config.nationalMode !== false,
            autoPlaceholder: "aggressive",
            countrySearch: config.countrySearch !== false, // Enable country search by default
            excludeCountries: ['ax'], // Exclude Åland Islands to avoid encoding issues
            utilsScript: typeof spai_form !== 'undefined' ? spai_form.plugin_url + 'assets/js/vendor/intl-tel-input/js/utils.js' : null
        });
        
        // Remove hidden field creation - we'll use the main field for E164
        
        // Function to adjust padding based on dial code length
        function adjustPaddingForDialCode() {
            const countryData = iti.getSelectedCountryData();
            const dialCodeLength = countryData.dialCode ? countryData.dialCode.length : 1;
            
            // Base padding + extra padding per digit
            const basePadding = 45; // For flag and spacing (increased by 10px)
            const perDigitPadding = 8; // Per digit of dial code
            const totalPadding = basePadding + (dialCodeLength * perDigitPadding);
            
            // Check if RTL
            const isRTL = document.dir === 'rtl' || document.documentElement.dir === 'rtl';
            
            if (isRTL) {
                phoneInput.style.paddingRight = totalPadding + 'px';
                phoneInput.style.paddingLeft = '10px';
            } else {
                phoneInput.style.paddingLeft = totalPadding + 'px';
                phoneInput.style.paddingRight = '10px';
            }
        }
        
        // Initial padding adjustment
        adjustPaddingForDialCode();
        
        // Format phone number based on country
        function formatPhoneNumber() {
            const value = phoneInput.value.replace(/\D/g, '');
            
            if (!value) {
                return;
            }
            
            const countryData = iti.getSelectedCountryData();
            const pattern = formatPatterns[countryData.iso2] || formatPatterns.default;
            const formatted = pattern.format(value);
            phoneInput.value = formatted;
        }
        
        // Handle input with formatting and length limits
        phoneInput.addEventListener('input', function(e) {
            const cursorPos = e.target.selectionStart;
            const oldLen = e.target.value.length;
            
            // Remove any non-digit characters immediately
            const digitsOnly = phoneInput.value.replace(/\D/g, '');
            if (phoneInput.value !== digitsOnly) {
                phoneInput.value = digitsOnly;
            }
            
            // Check length limits
            const countryData = iti.getSelectedCountryData();
            if (countryData) {
                const pattern = formatPatterns[countryData.iso2] || formatPatterns.default;
                
                if (digitsOnly.length > pattern.maxLength) {
                    const trimmed = digitsOnly.slice(0, pattern.maxLength);
                    phoneInput.value = trimmed;
                }
            }
            
            // Format the number
            formatPhoneNumber();
            
            // Adjust cursor position
            const newLen = e.target.value.length;
            const diff = newLen - oldLen;
            if (cursorPos && diff > 0) {
                e.target.setSelectionRange(cursorPos + diff, cursorPos + diff);
            }
            
            // Trigger validation callback if provided
            if (config.onValidation) {
                const isValid = validatePhoneNumber();
                config.onValidation(isValid);
            }
        });
        
        // Prevent non-digit characters from being typed
        phoneInput.addEventListener('keypress', function(e) {
            // Allow control keys (backspace, delete, tab, etc)
            if (e.ctrlKey || e.altKey || e.metaKey) {
                return;
            }
            
            // Get the character code
            const charCode = e.which || e.keyCode;
            
            // Allow only digits (0-9)
            if (charCode < 48 || charCode > 57) {
                e.preventDefault();
                return false;
            }
        });
        
        // Handle paste events
        phoneInput.addEventListener('paste', function(e) {
            e.preventDefault();
            
            // Get pasted text
            let pastedText = (e.clipboardData || window.clipboardData).getData('text');
            
            // Clean up common prefixes
            pastedText = pastedText.trim();
            pastedText = pastedText.replace(/^tel:/, '');
            pastedText = pastedText.replace(/^phone:/, '');
            pastedText = pastedText.replace(/^00/, '+');
            pastedText = pastedText.replace(/^011/, '+');
            
            // Remove extensions
            pastedText = pastedText.replace(/\s*(ext|x|extension)\.?\s*\d+.*$/i, '');
            
            // Extract only digits and + at the beginning
            let hasPlus = pastedText.startsWith('+');
            let digitsOnly = pastedText.replace(/\D/g, '');
            
            // Get current country data
            const countryData = iti.getSelectedCountryData();
            
            // Try to detect country from pasted number if it has a country code
            if (hasPlus && digitsOnly.length >= 10) {
                // Find matching country by checking dial codes (longest first)
                let detectedCountryCode = null;
                let detectedDialCode = null;
                
                // Check dial codes from longest to shortest
                for (let len = 4; len >= 1; len--) {
                    const possibleDialCode = digitsOnly.substring(0, len);
                    if (countryDialCodes[possibleDialCode]) {
                        detectedDialCode = possibleDialCode;
                        detectedCountryCode = countryDialCodes[possibleDialCode];
                        break;
                    }
                }
                
                // If we detected a different country, switch to it
                if (detectedCountryCode && detectedCountryCode !== countryData.iso2) {
                    iti.setCountry(detectedCountryCode);
                    
                    // Strip the detected country code
                    digitsOnly = digitsOnly.substring(detectedDialCode.length);
                } else if (digitsOnly.startsWith(countryData.dialCode)) {
                    // Same country, just strip the code
                    digitsOnly = digitsOnly.substring(countryData.dialCode.length);
                }
            } else if ((hasPlus || digitsOnly.length >= 10) && digitsOnly.startsWith(countryData.dialCode)) {
                // Not detecting country, but strip current country code if present
                digitsOnly = digitsOnly.substring(countryData.dialCode.length);
            }
            
            // Apply length limit using the current country (may have changed)
            const currentCountry = iti.getSelectedCountryData();
            const pattern = formatPatterns[currentCountry.iso2] || formatPatterns.default;
            if (digitsOnly.length > pattern.maxLength) {
                digitsOnly = digitsOnly.slice(0, pattern.maxLength);
            }
            
            // Set the cleaned value
            phoneInput.value = digitsOnly;
            
            // Format the number
            formatPhoneNumber();
            
            // Trigger validation
            if (config.onValidation) {
                const isValid = validatePhoneNumber();
                config.onValidation(isValid);
            }
        });
        
        // Format on blur
        phoneInput.addEventListener('blur', formatPhoneNumber);
        
        // Format when country changes
        phoneInput.addEventListener('countrychange', function() {
            adjustPaddingForDialCode(); // Adjust padding for new country
            formatPhoneNumber();
            if (config.onValidation) {
                const isValid = validatePhoneNumber();
                config.onValidation(isValid);
            }
        });
        
        // Validation function
        function validatePhoneNumber() {
            const value = phoneInput.value.trim();
            
            // If field is not required and empty, it's valid
            if (!config.required && !value) {
                return true;
            }
            
            // If field is required and empty, it's invalid
            if (config.required && !value) {
                return false;
            }
            
            // Get country data and extract digits only
            const countryData = iti.getSelectedCountryData();
            const digitsOnly = value.replace(/\D/g, '');
            
            // Get validation rule for the country
            const rule = validationRules[countryData.iso2] || validationRules.default;
            
            // Check if number length is within valid range
            const isValid = digitsOnly.length >= rule.min && digitsOnly.length <= rule.max;
            
            return isValid;
        }
        
        // Set existing number if provided
        function setNumber(number) {
            if (number) {
                iti.setNumber(number);
                setTimeout(formatPhoneNumber, 100);
            }
        }
        
        // Get number in E.164 format
        function getNumber() {
            // Get the current phone value
            const value = phoneInput.value.replace(/\D/g, '');
            if (!value) return '';
            
            // Get country data
            const countryData = iti.getSelectedCountryData();
            if (!countryData || !countryData.dialCode) return '';
            
            // Return E164 format
            return `+${countryData.dialCode}${value}`;
        }
        
        // Get validation status
        function isValid() {
            return validatePhoneNumber();
        }
        
        // Return API
        return {
            iti: iti,
            setNumber: setNumber,
            getNumber: getNumber,
            isValid: isValid,
            formatPhoneNumber: formatPhoneNumber
        };
    }
    
    // Public API
    return {
        init: init
    };
})();