/**
 * Pagaleve Eligibility Manager for WooCommerce Blocks Checkout
 * 
 * Uses registerPaymentMethodExtensionCallbacks to filter payment methods
 * based on customer eligibility via pre-analysis API.
 * 
 * @package Wc Pagaleve
 * @since 2.0.0
 */

import { registerPaymentMethodExtensionCallbacks } from '@woocommerce/blocks-registry';
import { dispatch, select } from '@wordpress/data';

const PATTERNS = {
    cpfDigits: /^\d{11}$/,
    phone: /^\d{10,11}$/,
    email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
};

const PESSOA_FISICA = '1';

let pendingRequest = null;

/**
 * Apply mask to a value based on a pattern
 * Pattern: '0' = digit, other chars = literal
 */
const maskByPattern = (value, pattern) => {
    if (!value) return '';
    const chars = value.replace(/[^a-zA-Z0-9]/g, '').split('');
    let result = '';
    let charIndex = 0;
    for (let i = 0; i < pattern.length && charIndex < chars.length; i++) {
        const p = pattern[i];
        const c = chars[charIndex];
        if (p === '0') {
            if (/\d/.test(c)) {
                result += c;
                charIndex++;
            } else {
                charIndex++;
                i--;
            }
        } else {
            result += p;
        }
    }
    return result;
};

/**
 * Apply masking to address fields
 */
const applyMasking = (address) => {
    const phone = address.phone || '';
    const phoneDigits = phone.replace(/\D/g, '');
    const phonePattern = phoneDigits.length >= 11 ? '(00) 00000-0000' : '(00) 0000-0000';

    return {
        'wc-pagaleve/cpf': maskByPattern(address['wc-pagaleve/cpf'], '000.000.000-00'),
        'wc-pagaleve/cnpj': maskByPattern(address['wc-pagaleve/cnpj'], '00.000.000/0000-00'),
        phone: maskByPattern(phone, phonePattern),
    };
};

/**
 * Setup masking hooks for checkout blocks
 */
const setupMaskingHooks = () => {
    if (typeof wp !== 'undefined' && wp.hooks) {
        wp.hooks.addAction(
            'experimental__woocommerce_blocks-checkout-set-billing-address',
            'wc-pagaleve/checkout-masker',
            (data) => {
                const cartStore = dispatch('wc/store/cart');
                const maskedFields = applyMasking(data.storeCart.billingAddress);
                cartStore.setBillingAddress({
                    ...data.storeCart.billingAddress,
                    ...maskedFields,
                });
            }
        );

        wp.hooks.addAction(
            'experimental__woocommerce_blocks-checkout-set-shipping-address',
            'wc-pagaleve/checkout-masker',
            (data) => {
                const cartStore = dispatch('wc/store/cart');
                const maskedFields = applyMasking(data.storeCart.shippingAddress);
                cartStore.setShippingAddress({
                    ...data.storeCart.shippingAddress,
                    ...maskedFields,
                });
            }
        );
    }
};

/**
 * Generate key for request deduplication
 */
const getRequestKey = (email, phone, cpf, personType, amount) => {
    return `${email}|${phone}|${cpf}|${personType}|${amount}`;
};

/**
 * Validate email format
 */
const isValidEmail = (email) => {
    return email && PATTERNS.email.test(email.trim());
};

/**
 * Validate phone format (10-11 digits)
 */
const isValidPhone = (phone) => {
    const digits = (phone || '').replace(/\D/g, '');
    return PATTERNS.phone.test(digits);
};

/**
 * Validate CPF format (11 digits)
 */
const isValidCpf = (cpf) => {
    const digits = (cpf || '').replace(/\D/g, '');
    return PATTERNS.cpfDigits.test(digits);
};

/**
 * Get additional field value from DOM
 * WooCommerce Blocks additional checkout fields
 */
const getAdditionalFieldValue = (fieldName) => {
    const selectors = [
        `#billing-wc-pagaleve\\/${fieldName}`,
        `[name="billing-wc-pagaleve/${fieldName}"]`,
        `#billing-wc-pagaleve-${fieldName}`,
        `[id*="wc-pagaleve"][id*="${fieldName}"]`,
        `[name*="wc-pagaleve"][name*="${fieldName}"]`,
        `#billing_${fieldName}`,
        `[name="billing_${fieldName}"]`,
    ];

    for (const selector of selectors) {
        try {
            const element = document.querySelector(selector);
            if (element && element.value) {
                return element.value;
            }
        } catch (e) {
        }
    }

    return '';
};

/**
 * Perform eligibility check via AJAX
 * Returns a Promise that resolves to boolean
 */
const checkEligibilityAsync = async (email, phone, cpf, personType, amount) => {
    const globals = window.PPWAGlobalVars || {};
    const ajaxUrl = globals.ajaxUrl || '/wp-admin/admin-ajax.php';

    try {
        const formData = new URLSearchParams();
        formData.append('action', globals.eligibilityAction || 'pagaleve_check_eligibility');
        formData.append('nonce', globals.eligibilityNonce || '');
        formData.append('email', email);
        formData.append('phone', phone.replace(/\D/g, ''));
        formData.append('person_type', personType);

        if (personType === PESSOA_FISICA && cpf) {
            formData.append('cpf', cpf);
        }


        const response = await fetch(ajaxUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: formData.toString(),
            credentials: 'same-origin',
        });

        const data = await response.json();

        if (data.success && data.data) {
            return data.data.eligible === true;
        }

        return true;
    } catch (error) {
        console.error('[Pagaleve] Eligibility check error:', error);
        return true;
    }
};

/**
 * Check eligibility with request deduplication
 */
const checkEligibility = async (email, phone, cpf, personType, amount) => {
    const requestKey = getRequestKey(email, phone, cpf, personType, amount);

    if (pendingRequest && pendingRequest.key === requestKey) {
        return pendingRequest.promise;
    }

    const promise = checkEligibilityAsync(email, phone, cpf, personType, amount);
    pendingRequest = { key: requestKey, promise };

    try {
        return await promise;
    } finally {
        pendingRequest = null;
    }
};

/**
 * Check if all required fields are filled for eligibility check.
 * 
 * @param {string} email Customer email.
 * @param {string} phone Customer phone.
 * @param {string} cpf Customer CPF.
 * @param {string} personType Person type (1 = PF, 2 = PJ).
 * @returns {boolean} True if all required fields are valid.
 */
const hasRequiredFields = (email, phone, cpf, personType) => {
    if (!isValidEmail(email)) {
        return false;
    }

    if (!isValidPhone(phone)) {
        return false;
    }

    if (personType === PESSOA_FISICA && !isValidCpf(cpf)) {
        return false;
    }

    return true;
};

/**
 * Callback for filtering Pagaleve payment methods
 * 
 * This function is called by WooCommerce Blocks whenever cart/checkout data changes.
 * It receives the current checkout state and must return a boolean synchronously.
 * 
 * Business Rules:
 * 1. Before any analysis: gateway is VISIBLE
 * 2. After analysis returns ineligible: gateway is HIDDEN
 * 3. Once hidden, gateway stays hidden until a new analysis returns eligible
 */
const canMakePaymentCallback = (checkoutData) => {
    const { billingAddress, cartTotals } = checkoutData;

    const email = billingAddress?.email || '';
    const phone = billingAddress?.phone || '';
    const amount = parseInt(cartTotals?.total_price || '0', 10);

    const personType = getAdditionalFieldValue('persontype') || PESSOA_FISICA;
    const cpf = getAdditionalFieldValue('cpf') || '';

    const requestKey = `${email}|${phone}|${cpf}|${personType}|${amount}`;

    if (window.pagaleveEligibilityStatus === false) {
        if (window.pagaleveLastRequestKey !== requestKey && hasRequiredFields(email, phone, cpf, personType)) {
            checkEligibility(email, phone, cpf, personType, amount).then((eligible) => {
                window.pagaleveLastRequestKey = requestKey;

                if (eligible) {
                    window.pagaleveEligibilityStatus = true;
                    forcePaymentMethodsRefresh();
                }
            });
        }
        return false;
    }

    if (window.pagaleveLastRequestKey === requestKey && window.pagaleveEligibilityStatus !== undefined) {
        return window.pagaleveEligibilityStatus;
    }

    if (!hasRequiredFields(email, phone, cpf, personType)) {
        return true;
    }

    checkEligibility(email, phone, cpf, personType, amount).then((eligible) => {
        window.pagaleveLastRequestKey = requestKey;
        window.pagaleveEligibilityStatus = eligible;

        if (!eligible) {
            forcePaymentMethodsRefresh();
        }
    });

    return true;
};

/**
 * Force WooCommerce Blocks to re-evaluate payment methods
 */
const forcePaymentMethodsRefresh = () => {
    const cartStore = dispatch('wc/store/cart');
    const currentBilling = select('wc/store/cart').getCustomerData()?.billingAddress || {};
    cartStore.setBillingAddress({ ...currentBilling });
};

/**
 * Classic Checkout Eligibility Handler
 */
const setupClassicCheckoutHandler = () => {
    const $ = window.jQuery;
    if (!$) return;

    let isChecking = false;
    let lastCheckedData = null;
    let debounceTimer = null;
    const DEBOUNCE_DELAY = 500;

    /**
     * Get billing data from form
     */
    const getBillingData = () => {
        return {
            email: $('#billing_email').val() || '',
            phone: $('#billing_phone').val() || '',
            cpf: $('#billing_cpf').val() || '',
            cnpj: $('#billing_cnpj').val() || '',
            personType: $('#billing_persontype').val() || PESSOA_FISICA,
        };
    };

    /**
     * Check if data has changed
     */
    const hasDataChanged = (data) => {
        if (!lastCheckedData) return true;
        return (
            data.email !== lastCheckedData.email ||
            data.phone !== lastCheckedData.phone ||
            data.cpf !== lastCheckedData.cpf ||
            data.personType !== lastCheckedData.personType
        );
    };

    /**
     * Perform eligibility check
     */
    const checkEligibilityClassic = () => {
        const data = getBillingData();

        if (!isValidEmail(data.email)) {
            return;
        }

        if (!isValidPhone(data.phone)) {
            return;
        }

        if (data.personType === PESSOA_FISICA && !isValidCpf(data.cpf)) {
            return;
        }

        if (!hasDataChanged(data)) {
            return;
        }

        if (isChecking) {
            return;
        }

        isChecking = true;
        lastCheckedData = { ...data };


        const globals = window.PPWAGlobalVars || {};
        const ajaxUrl = globals.ajaxUrl || window.wc_checkout_params?.ajax_url || '/wp-admin/admin-ajax.php';

        $.ajax({
            type: 'POST',
            url: ajaxUrl,
            dataType: 'json',
            data: {
                action: globals.eligibilityAction || 'pagaleve_check_eligibility',
                nonce: globals.eligibilityNonce || '',
                email: data.email,
                phone: data.phone,
                cpf: data.personType === PESSOA_FISICA ? data.cpf : '',
                person_type: data.personType,
            },
            success: function (response) {
                isChecking = false;

                $(document.body).trigger('update_checkout');
            },
            error: function (error) {
                isChecking = false;
                console.error('[Pagaleve Classic] Eligibility check error:', error);
                $(document.body).trigger('update_checkout');
            },
        });
    };

    /**
     * Schedule check with debounce
     */
    const scheduleCheck = () => {
        if (debounceTimer) {
            clearTimeout(debounceTimer);
        }
        debounceTimer = setTimeout(checkEligibilityClassic, DEBOUNCE_DELAY);
    };

    $(document).on('change keyup', '#billing_email, #billing_phone, #billing_cpf, #billing_cnpj, #billing_persontype', function () {
        scheduleCheck();
    });

    $(document.body).on('updated_checkout', function () {
        const data = getBillingData();
        if (isValidEmail(data.email) && isValidPhone(data.phone)) {
            scheduleCheck();
        }
    });

    $(document).ready(function () {
        const data = getBillingData();
        if (data.email || data.phone) {
            scheduleCheck();
        }
    });

};

if (document.querySelector('form.checkout')) {
    setupClassicCheckoutHandler();
} else {
    setupMaskingHooks();

    registerPaymentMethodExtensionCallbacks('wc-pagaleve', {
        'pagaleve-pix': canMakePaymentCallback,
    });

}
