/**
 * Card on file — collect a card with Stripe Elements and store it for later.
 *
 * Nothing here ever sees a card number: Elements renders Stripe's own iframe,
 * confirmCardSetup talks to Stripe directly from the browser, and all this
 * file passes back to WordPress is a SetupIntent id that the server re-verifies
 * against Stripe before trusting it.
 */
(function ($) {
    'use strict';

    var __ = (function () {
        var d = 'yatoon-booking-system';
        if (typeof window !== 'undefined' && window.wp && window.wp.i18n && typeof window.wp.i18n.__ === 'function') {
            return function (s) { return window.wp.i18n.__(s, d); };
        }
        return function (s) { return s; };
    })();

    var state = {
        stripe: null,
        elements: null,
        card: null,
        mounted: false,
        saving: false
    };

    function cfg() {
        return (typeof window.yatoonCof !== 'undefined') ? window.yatoonCof : null;
    }

    function status(message, kind) {
        var $el = $('#yatoon-cof-status');
        if (!$el.length) { return; }
        $el.removeClass('is-error is-success is-working');
        if (kind) { $el.addClass('is-' + kind); }
        $el.text(message || '');
    }

    function contact() {
        return {
            name: $.trim($('#sbs-customer-name, [name="customer_name"]').first().val() || ''),
            email: $.trim($('#sbs-customer-email, [name="customer_email"]').first().val() || ''),
            phone: $.trim($('#sbs-customer-phone, [name="customer_phone"]').first().val() || '')
        };
    }

    /**
     * Mount the card field the first time the details step is visible.
     *
     * Elements refuses to mount into a hidden container, so this is deferred
     * rather than done on document ready.
     */
    function mount() {
        var c = cfg();
        if (state.mounted || !c || !c.publishableKey) { return; }
        var $box = $('#yatoon-cof-element');
        if (!$box.length || !$box.is(':visible')) { return; }
        if (typeof window.Stripe !== 'function') {
            status(__('The card form could not load. You can still book; we will take payment at the salon.'), 'error');
            return;
        }
        state.stripe = window.Stripe(c.publishableKey);
        state.elements = state.stripe.elements();
        state.card = state.elements.create('card', {
            hidePostalCode: false,
            style: {
                base: {
                    fontSize: '16px',           // below 16px iOS zooms the page on focus
                    color: '#1f2937',
                    fontFamily: 'inherit',
                    '::placeholder': { color: '#9ca3af' }
                },
                invalid: { color: '#b4232b' }
            }
        });
        state.card.mount('#yatoon-cof-element');
        state.card.on('change', function (event) {
            if (event.error) {
                status(event.error.message, 'error');
            } else if (status.lastWasError) {
                status('');
            }
        });
        state.mounted = true;
    }

    function markSaved(brand, last4) {
        $('#yatoon-cof-saved').val('1');
        $('#yatoon-cof-box').addClass('is-saved');
        $('#yatoon-cof-save').prop('disabled', true);
        var label = brand ? (brand.charAt(0).toUpperCase() + brand.slice(1)) : __('Card');
        status(label + ' •••• ' + (last4 || '') + ' — ' + __('saved'), 'success');
    }

    function save() {
        var c = cfg();
        if (state.saving || !c) { return; }
        if (!state.mounted) {
            mount();
            if (!state.mounted) { return; }
        }
        if (!$('#yatoon-cof-consent').is(':checked')) {
            status(__('Please agree to the cancellation policy first.'), 'error');
            return;
        }
        var who = contact();
        if (!who.email && !who.phone) {
            status(__('Enter your email or phone number first.'), 'error');
            return;
        }

        state.saving = true;
        $('#yatoon-cof-save').prop('disabled', true);
        status(__('Checking your card...'), 'working');

        var otpSection = document.getElementById('sbs-otp-section');
        // 4.6.2: report the channel the customer actually verified through,
        // rather than re-deriving it from the site setting. The old line read
        // yatoonData.verifySmsOtp, so on a site with SMS verification enabled
        // it always claimed 'sms' even when the code had gone out by email,
        // and the server rejected a perfectly good receipt -- which locked a
        // returning customer out of updating their own card.
        //
        // Whichever element issued the receipt records it alongside; if it did
        // not, fall back to the old inference. This value is a hint only: the
        // server reads the real channel off the receipt itself, so a stale or
        // missing dataset value can no longer break verification.
        var verifiedChannel = otpSection && (otpSection.dataset.verifiedChannel || otpSection.dataset.channel);
        var otpChannel = verifiedChannel
            || ((typeof yatoonData !== 'undefined' && yatoonData.verifySmsOtp === '1') ? 'sms' : 'email');
        $.post(c.ajaxUrl, {
            action: 'yatoon_cof_setup_intent',
            nonce: c.nonce,
            customer_name: who.name,
            customer_email: who.email,
            customer_phone: who.phone,
            otp_channel: otpChannel,
            otp_receipt: otpSection && otpSection.dataset.verifiedKey ? otpSection.dataset.verifiedKey : ''
        }).done(function (resp) {
            if (!resp || !resp.success || !resp.data || !resp.data.client_secret) {
                state.saving = false;
                $('#yatoon-cof-save').prop('disabled', false);
                status((resp && resp.data && resp.data.message) || __('The card could not be saved. Please try again.'), 'error');
                return;
            }
            state.stripe.confirmCardSetup(resp.data.client_secret, {
                payment_method: {
                    card: state.card,
                    billing_details: { name: who.name, email: who.email, phone: who.phone }
                }
            }).then(function (result) {
                if (result.error) {
                    state.saving = false;
                    $('#yatoon-cof-save').prop('disabled', false);
                    status(result.error.message || __('Your bank declined the card.'), 'error');
                    return;
                }
                $.post(c.ajaxUrl, {
                    action: 'yatoon_cof_save_card',
                    nonce: c.nonce,
                    setup_intent_id: result.setupIntent.id,
                    setup_authorization: resp.data.setup_authorization || '',
                    consent: 1
                }).done(function (saveResp) {
                    state.saving = false;
                    if (saveResp && saveResp.success) {
                        markSaved(saveResp.data.brand, saveResp.data.last4);
                    } else {
                        $('#yatoon-cof-save').prop('disabled', false);
                        status((saveResp && saveResp.data && saveResp.data.message) || __('The card could not be saved.'), 'error');
                    }
                }).fail(function () {
                    state.saving = false;
                    $('#yatoon-cof-save').prop('disabled', false);
                    status(__('We could not reach the salon to finish saving your card.'), 'error');
                });
            });
        }).fail(function () {
            state.saving = false;
            $('#yatoon-cof-save').prop('disabled', false);
            status(__('We could not reach the salon. Please try again.'), 'error');
        });
    }

    $(function () {
        if (!cfg()) { return; }

        $(document).on('click', '#yatoon-cof-save', function (e) {
            e.preventDefault();
            save();
        });

        // The details step is revealed by the booking script, not by a page
        // load, so watch for it becoming visible instead of mounting eagerly.
        $(document).on('click', '.sbs-btn-next, .sbs-prog-step, #sbs-cart-next-btn, #sbs-sidebar-next-btn', function () {
            window.setTimeout(mount, 260);
        });
        window.setTimeout(mount, 800);

        // A required card must actually be saved before the booking is sent.
        $(document).on('submit', '.sbs-booking-form, #sbs-booking-form', function (e) {
            var $box = $('#yatoon-cof-box');
            if (!$box.length || $box.data('required') !== 1 && $box.attr('data-required') !== '1') { return; }
            if ($('#yatoon-cof-saved').val() === '1') { return; }
            e.preventDefault();
            e.stopImmediatePropagation();
            status(__('Please save a card before confirming your appointment.'), 'error');
            $box[0].scrollIntoView({ block: 'center', behavior: 'smooth' });
        });
    });
})(jQuery);
