/**
 * ZainPay WooCommerce Payment Gateway JavaScript
 */

jQuery(document).ready(function($) {
    'use strict';

    /**
     * Object to handle ZainPay payment form.
     */
    var pgzw_form = {

        /**
         * Initialize event handlers and UI updates.
         */
        init: function() {
            // Handle payment form submission
            $(document.body).on('checkout_place_order_pgzw_zainpay checkout_place_order_pgzw', this.onSubmit);
            
            // Handle payment method selection
            $('form.checkout').on('change', 'input[name="payment_method"]', this.onPaymentMethodChange);
            
            // Handle inline payment form submission
            $(document).on('submit', '#pgzw-payment-form', this.handleInlinePayment);
            
            // Initialize on page load
            this.onPaymentMethodChange();
            
            // Auto-trigger inline popup on order-pay page
            this.autoTriggerOnOrderPay();
        },

        /**
         * Compute same-origin AJAX URL from localized value
         */
        getAjaxUrl: function() {
            try {
                var a = document.createElement('a');
                a.href = pgzw_params.ajax_url;
                var pathAndQuery = a.pathname + a.search;
                return window.location.origin + pathAndQuery;
            } catch (e) {
                return pgzw_params.ajax_url;
            }
        },

        /**
         * Handle payment method selection change.
         */
        onPaymentMethodChange: function() {
            var selectedPaymentMethod = $('input[name="payment_method"]:checked').val();
            
            // On order-pay page, there's no payment method selection, so always show the form
            if ($('#pgzw-payment-form').length > 0) {
                pgzw_form.showPaymentForm();
                return;
            }
            
            // On checkout page, check selected payment method
            if ('pgzw_zainpay' === selectedPaymentMethod) {
                pgzw_form.showPaymentForm();
            } else {
                pgzw_form.hidePaymentForm();
            }
        },

        /**
         * Auto-trigger inline payment popup as soon as order-pay page loads
         */
        autoTriggerOnOrderPay: function() {
            try {
                // Only on order-pay page where our inline form exists
                var $form = $('#pgzw-payment-form');
                if (!$form.length) { return; }

                // Only for inline payment option
                if (!window.pgzw_params || pgzw_params.payment_page !== 'inline') { return; }

                // Prevent double-triggering
                if ($form.data('pgzw-auto-triggered')) { return; }
                $form.data('pgzw-auto-triggered', true);

                // Slight delay to ensure bindings and DOM are fully ready
                setTimeout(function() {
                    try { if (pgzw_params && pgzw_params.debug === 'yes') { console.log('ZainPay: auto-triggering inline payment on order-pay page'); } } catch(_) {}
                    $form.trigger('submit');
                }, 100);
            } catch (e) {
                try { if (pgzw_params && pgzw_params.debug === 'yes') { console.warn('ZainPay auto-trigger failed:', e); } } catch(_) {}
            }
        },

        /**
         * Show ZainPay payment form.
         */
        showPaymentForm: function() {
            $('#pgzw-payment-form, .pgzw-payment-fields').slideDown(200);
        },

        /**
         * Hide ZainPay payment form.
         */
        hidePaymentForm: function() {
            $('#pgzw-payment-form, .pgzw-payment-fields').slideUp(200);
        },

        /**
         * Initialize inline payment from checkout form (server initializes and returns hosted URL).
         */
        initializeInlinePayment: function() {
            // Show loading state
            $('body').addClass('processing');
            $('.woocommerce-checkout-payment').block({
                message: null,
                overlayCSS: { background: '#fff', opacity: 0.6 }
            });

            var checkoutForm = $('form.checkout');
            var formData = checkoutForm.serialize();

            $.ajax({
                url: pgzw_form.getAjaxUrl() + '?action=pgzw_create_order_and_init_payment',
                type: 'POST',
                data: formData + '&action=pgzw_create_order_and_init_payment&nonce=' + pgzw_params.nonce,
                success: function(response) {
                    $('body').removeClass('processing');
                    $('.woocommerce-checkout-payment').unblock();

                    if (response && response.success && response.data) {
                        // Prefer inline payload if provided
                        if (response.data.inline && window.zainpayInitPayment) {
                            try {
                                pgzw_form.startInlinePayment(response.data.inline, response.data);
                            } catch (e) {
                                try { if (pgzw_params && pgzw_params.debug === 'yes') { console.error('ZainPay inline SDK error:', e); } } catch(_) {}
                                if (response.data.redirect_url) {
                                    pgzw_form.openHostedPopup(response.data.redirect_url);
                                    pgzw_form.pollPaymentStatus(response.data.order_id);
                                } else {
                                    pgzw_form.form.showError('Payment initialization failed.');
                                }
                            }
                            return;
                        }
                        // Fallback to hosted URL flow
                        if (response.data.redirect_url) {
                            pgzw_form.openHostedPopup(response.data.redirect_url);
                            pgzw_form.pollPaymentStatus(response.data.order_id);
                            return;
                        }
                    }

                    var msg = (response && response.data && response.data.message) ? response.data.message : 'Order creation failed. Please try again.';
                    pgzw_form.form.showError(msg);
                },
                error: function(xhr) {
                    $('body').removeClass('processing');
                    $('.woocommerce-checkout-payment').unblock();
                    var msg = 'Order creation failed. Please try again.';
                    try {
                        if (xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
                            msg = xhr.responseJSON.data.message;
                        } else if (xhr && xhr.responseText) {
                            msg = xhr.responseText.substring(0, 500);
                        }
                    } catch(e) {}
                    pgzw_form.form.showError(msg);
                }
            });
        },

        /**
         * Handle inline payment form submission (for order-pay page).
         */
        handleInlinePayment: function(e) {
            e.preventDefault();
            var form = $(this);
            var submitButton = form.find('#pgzw-submit-payment');
            submitButton.prop('disabled', true).text('Processing...');

            var paymentData = {
                action: 'pgzw_process_inline_payment',
                nonce: pgzw_params.nonce,
                payment_data: {
                    order_id: $('#pgzw-order-id').val() || 0,
                    reference: $('#pgzw-reference').val() || ''
                }
            };

            $.ajax({
                url: pgzw_form.getAjaxUrl() + '?action=pgzw_process_inline_payment',
                type: 'POST',
                data: paymentData,
                success: function(resp) {
                    submitButton.prop('disabled', false).text('Pay Now');
                    if (resp && resp.success && resp.data) {
                        if (resp.data.inline && window.zainpayInitPayment) {
                            try {
                                pgzw_form.startInlinePayment(resp.data.inline, resp.data);
                            } catch (e) {
                                try { if (pgzw_params && pgzw_params.debug === 'yes') { console.error('ZainPay inline SDK error:', e); } } catch(_) {}
                                if (resp.data.redirect_url) {
                                    pgzw_form.openHostedPopup(resp.data.redirect_url);
                                    pgzw_form.pollPaymentStatus(resp.data.order_id);
                                } else {
                                    pgzw_form.form.showError('Payment initialization failed.');
                                }
                            }
                            return;
                        }
                        if (resp.data.redirect_url) {
                            pgzw_form.openHostedPopup(resp.data.redirect_url);
                            pgzw_form.pollPaymentStatus(resp.data.order_id);
                            return;
                        }
                    }
                    var msg = (resp && resp.data && resp.data.message) ? resp.data.message : 'Payment initialization failed. Please try again.';
                    pgzw_form.form.showError(msg);
                },
                error: function(xhr, status, errorThrown) {
                    submitButton.prop('disabled', false).text('Pay Now');
                    var msg = 'Payment initialization failed. Please try again.';
                    try {
                        if (xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
                            msg = xhr.responseJSON.data.message;
                        } else if (xhr && xhr.responseText) {
                            msg = xhr.responseText.substring(0, 500);
                        }
                    } catch(e) {}
                    pgzw_form.form.showError(msg);
                }
            });
        },

        /**
         * Hand the payload to the inline SDK and wire up status tracking.
         *
         * The SDK replaces payload.txnRef with a reference of its own before
         * it calls ZainPay, so the value we sent never reaches them. It
         * mutates the object we pass in, which lets us read the substituted
         * reference straight back off it and record it against the order.
         */
        startInlinePayment: function(payload, data) {
            zainpayInitPayment(payload, function() {
                pgzw_form.recordTxnRef(data, payload.txnRef, function() {
                    try { pgzw_form.checkAndRedirectOnce(data.order_id); } catch (_) {}
                    pgzw_form.pollPaymentStatus(data.order_id);
                });
            }, pgzw_params.public_key, pgzw_params.mode);

            // Record immediately too, so polling works even if the SDK's
            // completion callback never fires.
            pgzw_form.recordTxnRef(data, payload.txnRef, function() {
                pgzw_form.pollPaymentStatus(data.order_id);
            });

            setTimeout(function() { pgzw_form.injectInlineSummary(payload); }, 100);
        },

        /**
         * Persist the reference the inline SDK generated against the order.
         */
        recordTxnRef: function(data, txnRef, done) {
            var finish = function() { if (done) { done(); } };

            if (!txnRef || !data || !data.order_id || !data.order_key || txnRef === pgzw_form._recordedRef) {
                finish();
                return;
            }
            pgzw_form._recordedRef = txnRef;

            $.ajax({
                url: pgzw_form.getAjaxUrl() + '?action=pgzw_record_txn_ref',
                type: 'POST',
                data: {
                    action: 'pgzw_record_txn_ref',
                    nonce: pgzw_params.nonce,
                    order_id: data.order_id,
                    order_key: data.order_key,
                    txn_ref: txnRef
                }
            }).always(function() {
                try {
                    if (pgzw_params && pgzw_params.debug === 'yes') {
                        console.log('ZainPay: recorded inline reference', txnRef);
                    }
                } catch (_) {}
                finish();
            });
        },

        /**
         * Open a centered popup window for the hosted authorization URL
         */
        openHostedPopup: function(url) {
            var width = 520;
            var height = 720;
            var left = (window.screen.width / 2) - (width / 2);
            var top = (window.screen.height / 2) - (height / 2);
            window.open(url, 'ZainPayCheckout', 'menubar=no,location=no,resizable=yes,scrollbars=yes,status=no,width=' + width + ',height=' + height + ',top=' + top + ',left=' + left);
        },

        /**
         * Try to inject amount and email summary into ZainPay inline popup once it exists
         */
        injectInlineSummary: function(payload) {
            try {
                var tries = 0;
                var maxTries = 50; // ~5s
                var timer = setInterval(function(){
                    tries++;
                    var emailEl = document.querySelector('#pgzw-modal #payeeEmail');
                    var amountEl = document.querySelector('#pgzw-modal #amountToPay');
                    if (emailEl && amountEl) {
                        clearInterval(timer);
                        // Email
                        if (payload && payload.emailAddress) {
                            emailEl.textContent = payload.emailAddress;
                        }
                        // Amount
                        if (payload && payload.amount) {
                            var amtText = pgzw_form.formatAmount(payload.amount, payload.currencyCode || 'NGN');
                            amountEl.textContent = amtText;
                        }
                    } else if (tries >= maxTries) {
                        clearInterval(timer);
                    }
                }, 100);
            } catch (e) {
                try { if (pgzw_params && pgzw_params.debug === 'yes') { console.warn('ZainPay summary inject failed:', e); } } catch(_) {}
            }
        },

        /**
         * Format amount with currency
         */
        formatAmount: function(amount, currency) {
            var num = 0;
            try { num = parseFloat(String(amount).replace(/,/g, '')); } catch(_) {}
            var code = (currency || 'NGN').toUpperCase();
            var symbol = code;
            if (code === 'NGN') symbol = '₦';
            else if (code === 'USD') symbol = '$';
            else if (code === 'GBP') symbol = '£';
            else if (code === 'EUR') symbol = '€';
            var formatted = isFinite(num) ? num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : String(amount);
            return symbol + ' ' + formatted;
        },

        /**
         * Poll order status until it becomes processing/completed or fails
         */
        pollPaymentStatus: function(orderId) {
            var params = window.pgzw_params || {};

            var baseInterval = parseInt(params.poll_interval || 2000, 10);
            if (!isFinite(baseInterval) || baseInterval < 500) {
                baseInterval = 2000;
            }

            var maxInterval = parseInt(params.poll_max_interval || 10000, 10);
            if (!isFinite(maxInterval) || maxInterval < baseInterval) {
                maxInterval = Math.max(baseInterval, 10000);
            }

            var maxDurationMs = parseInt(params.poll_max_duration || 180000, 10);
            if (!isFinite(maxDurationMs) || maxDurationMs < baseInterval) {
                maxDurationMs = 180000;
            }

            var stopPolling = function() {
                if (pgzw_form._pollHandle) {
                    clearTimeout(pgzw_form._pollHandle);
                    pgzw_form._pollHandle = null;
                }
                if (pgzw_form._pollState && pgzw_form._pollState.visibilityHandler) {
                    document.removeEventListener('visibilitychange', pgzw_form._pollState.visibilityHandler);
                }
                pgzw_form._pollState = null;
            };

            stopPolling();

            var pollState = {
                startedAt: Date.now(),
                attempt: 0,
                inFlight: false,
                stopped: false,
                visibilityHandler: null
            };
            pgzw_form._pollState = pollState;

            var computeNextDelay = function(attempt) {
                var factor = 1.35;
                var delay = Math.round(baseInterval * Math.pow(factor, attempt));
                delay = Math.min(maxInterval, Math.max(baseInterval, delay));
                var jitter = Math.floor(Math.random() * 250);
                return delay + jitter;
            };

            var schedule = function(delayMs) {
                if (pollState.stopped) return;
                if (pgzw_form._pollHandle) {
                    clearTimeout(pgzw_form._pollHandle);
                }
                pgzw_form._pollHandle = setTimeout(tick, delayMs);
            };

            var tick = function() {
                if (pollState.stopped) return;

                if ((Date.now() - pollState.startedAt) > maxDurationMs) {
                    pollState.stopped = true;
                    stopPolling();
                    pgzw_form.form.showError('Payment is taking longer than expected. Please refresh this page to check the latest status.');
                    return;
                }

                if (document.hidden) {
                    schedule(Math.min(maxInterval, Math.max(baseInterval * 2, 5000)));
                    return;
                }

                if (pollState.inFlight) {
                    return;
                }
                pollState.inFlight = true;

                $.ajax({
                    url: pgzw_form.getAjaxUrl() + '?action=pgzw_check_payment_status',
                    type: 'POST',
                    data: {
                        action: 'pgzw_check_payment_status',
                        nonce: params.status_nonce || params.nonce,
                        order_id: orderId
                    },
                    timeout: Math.max(15000, maxInterval + 5000),
                    beforeSend: function() {
                        try { if (params && params.debug === 'yes') { console.log('ZainPay AJAX (poll) ->', pgzw_form.getAjaxUrl() + '?action=pgzw_check_payment_status', {orderId: orderId}); } } catch(e) {}
                    }
                }).done(function(res) {
                    if (!res) {
                        pollState.attempt++;
                        schedule(computeNextDelay(pollState.attempt));
                        return;
                    }

                    if (res.success && res.data) {
                        if (res.data.redirect_url && (res.data.status === 'processing' || res.data.status === 'success' || res.data.status === 'on-hold')) {
                            pollState.stopped = true;
                            stopPolling();
                            window.location.href = res.data.redirect_url;
                            return;
                        }
                        if (res.data.status === 'processing' || res.data.status === 'success' || res.data.status === 'on-hold') {
                            pollState.stopped = true;
                            stopPolling();
                            window.location.href = res.data.redirect_url || params.return_url;
                            return;
                        }
                    } else if (res && res.data && (res.data.status === 'failed' || res.data.status === 'cancelled')) {
                        pollState.stopped = true;
                        stopPolling();
                        pgzw_form.form.showError(res.data.message || 'Payment was not successful.');
                        return;
                    }

                    pollState.attempt++;
                    schedule(computeNextDelay(pollState.attempt));
                }).fail(function(xhr, status, errorThrown) {
                    try { if (params && params.debug === 'yes') { console.warn('ZainPay poll error:', {status: status, error: errorThrown, xhr: xhr}); } } catch(_) {}
                    pollState.attempt++;
                    schedule(computeNextDelay(pollState.attempt));
                }).always(function() {
                    pollState.inFlight = false;
                });
            };

            pollState.visibilityHandler = function() {
                if (pollState.stopped) return;
                if (!document.hidden) {
                    schedule(0);
                }
            };
            document.addEventListener('visibilitychange', pollState.visibilityHandler);

            schedule(baseInterval);
        },

        /**
         * Perform a one-off status check and redirect immediately if server provides redirect_url.
         */
        checkAndRedirectOnce: function(orderId) {
            $.ajax({
                url: pgzw_form.getAjaxUrl() + '?action=pgzw_check_payment_status',
                type: 'POST',
                data: {
                    action: 'pgzw_check_payment_status',
                    nonce: pgzw_params.status_nonce || pgzw_params.nonce, // Use status_nonce if available, fallback to regular nonce
                    order_id: orderId,
                    from_callback: 1
                },
                success: function(res) {
                    if (!res) return;
                    if (res.success && res.data && res.data.redirect_url) {
                        if (pgzw_form._pollHandle) { clearTimeout(pgzw_form._pollHandle); pgzw_form._pollHandle = null; }
                        if (pgzw_form._pollState && pgzw_form._pollState.visibilityHandler) {
                            document.removeEventListener('visibilitychange', pgzw_form._pollState.visibilityHandler);
                        }
                        pgzw_form._pollState = null;
                        window.location.href = res.data.redirect_url;
                    }
                }
            });
        },

        /**
         * Handle form submission.
         */
        onSubmit: function() {
            return pgzw_form.form.onSubmit();
        },

        /**
         * Form object.
         */
        form: {
            /**
             * Handle form submission.
             */
            onSubmit: function() {
                // Basic validation
                if (!pgzw_form.form.isFormValid()) {
                    return false;
                }

                // For inline payments, prevent default submission and handle hosted popup
                if ('inline' === pgzw_params.payment_page) {
                    pgzw_form.initializeInlinePayment();
                    return false; // Prevent default form submission
                }

                // For redirect payments, proceed normally
                return true;
            },

            /**
             * Validate form fields.
             */
            isFormValid: function() {
                var errors = [];
                
                // Add any custom validation here
                
                if (errors.length > 0) {
                    pgzw_form.form.showError(errors.join('<br>'));
                    return false;
                }
                
                return true;
            },

            /**
             * Show error message.
             */
            showError: function(message) {
                var safeMessage = pgzw_form.form.formatMessage(message);
                $('.woocommerce-error, .woocommerce-message').remove();
                var $container = $('form.checkout');
                if (!$container.length) {
                    $container = $('#pgzw-payment-form');
                }
                if ($container.length) {
                    $container.prepend('<div class="woocommerce-error">' + safeMessage + '</div>');
                    var top = ($container.offset() && $container.offset().top) ? ($container.offset().top - 100) : 0;
                    $('html, body').animate({ scrollTop: top }, 1000);
                } else {
                    // Fallback: append to body
                    $('body').prepend('<div class="woocommerce-error" style="margin: 1em 0;">' + safeMessage + '</div>');
                }
            },

            /**
             * Show success message.
             */
            showSuccess: function(message) {
                var safeMessage = pgzw_form.form.formatMessage(message);
                $('.woocommerce-error, .woocommerce-message').remove();
                var $container = $('form.checkout');
                if (!$container.length) {
                    $container = $('#pgzw-payment-form');
                }
                if ($container.length) {
                    $container.prepend('<div class="woocommerce-message">' + safeMessage + '</div>');
                    var top = ($container.offset() && $container.offset().top) ? ($container.offset().top - 100) : 0;
                    $('html, body').animate({ scrollTop: top }, 1000);
                } else {
                    // Fallback: append to body
                    $('body').prepend('<div class="woocommerce-message" style="margin: 1em 0;">' + safeMessage + '</div>');
                }
            },

            formatMessage: function(message) {
                var parts = String(message).split('<br>');
                var safeParts = parts.map(function(part) {
                    return $('<div/>').text(part).html();
                });
                return safeParts.join('<br>');
            }
        }
    };

    pgzw_form.init();
});
