/**
 * WooLentor Cart Page — Shared JS
 *
 * Handles quantity stepper interactions and AJAX cart updates for ALL
 * cart-page widget styles (Aura, Noir, Canvas … Lux).
 *
 * Selectors used:
 *   .wl-cart-table-wrap  — present on every cart table style wrapper
 *   .wl-cart-total-wrap  — present on every cart total style wrapper
 *   .wl-cart-item        — individual item card
 *   .wl-qty-stepper__btn — +/- stepper buttons
 *   input.qty            — quantity input
 *
 * All listeners are delegated on `document` so they survive DOM swaps
 * after the in-place cart refresh.
 *
 * @package WooLentor Pro
 */
( function () {
    'use strict';

    if ( typeof wlCartPageParams === 'undefined' ) {
        return;
    }

    var AJAX_URL  = wlCartPageParams.ajaxUrl;
    var NONCE     = wlCartPageParams.nonce;
    var TABLE_SEL = '.wl-cart-table-wrap';
    var TOTAL_SEL = '.wl-cart-total-wrap';
    var timers    = {};

    // ── Express checkout visibility ──────────────────────────────────────────
    function initExpressCheckout() {
        document.querySelectorAll( '.wl-express-checkout' ).forEach( function ( el ) {
            var btns = el.querySelector( '.wl-express-checkout__btns' );
            if ( btns && btns.children.length > 0 ) {
                el.classList.add( 'wl-express-checkout--visible' );
            }
        } );
    }
    initExpressCheckout();
    setTimeout( initExpressCheckout, 1500 );

    // ── Shipping method change ───────────────────────────────────────────────
    // WooCommerce's own cart.js already handles the AJAX for shipping method
    // updates (posts to ?wc-ajax=update_shipping_method, saves to session,
    // recalculates totals). We just show our loading overlay and re-render
    // our template once WC fires the updated_shipping_method jQuery event.
    document.addEventListener( 'change', function ( e ) {
        var input = e.target.closest( 'input.shipping_method' );
        if ( ! input || ! input.closest( TOTAL_SEL ) ) return;
        var wrap = input.closest( TOTAL_SEL );
        if ( wrap ) wrap.classList.add( 'wl-updating' );
    } );

    if ( window.jQuery ) {
        jQuery( document.body ).on( 'updated_shipping_method', function () {
            refreshSections( '' );
        } );
    }

    // ── Coupon form submit (apply) ────────────────────────────────────────────
    document.addEventListener( 'submit', function ( e ) {
        var form = e.target.closest( '.wl-coupon-form' );
        if ( ! form || ! form.closest( TOTAL_SEL ) ) return;

        e.preventDefault();

        var codeInput = form.querySelector( 'input[name="coupon_code"]' );
        var code      = codeInput ? codeInput.value.trim() : '';
        if ( ! code ) return;

        var wrap = form.closest( TOTAL_SEL );
        if ( wrap ) wrap.classList.add( 'wl-updating' );

        var fd = new FormData();
        fd.append( 'action',      'wl_cart_apply_coupon' );
        fd.append( 'nonce',       NONCE );
        fd.append( 'coupon_code', code );

        fetch( AJAX_URL, { method: 'POST', body: fd, credentials: 'same-origin' } )
            .then( function ( r ) { return r.json(); } )
            .then( function ( res ) {
                var noticesHtml = ( res.data && res.data.notices_html ) ? res.data.notices_html : '';
                refreshSections( noticesHtml );
            } )
            .catch( function () {
                if ( wrap ) wrap.classList.remove( 'wl-updating' );
            } );
    } );

    // ── Coupon remove link click ──────────────────────────────────────────────
    document.addEventListener( 'click', function ( e ) {
        var removeLink = e.target.closest( '.woocommerce-remove-coupon' );
        if ( ! removeLink || ! removeLink.closest( TOTAL_SEL ) ) return;

        e.preventDefault();

        var code = removeLink.dataset.coupon;
        if ( ! code ) return;

        var wrap = removeLink.closest( TOTAL_SEL );
        if ( wrap ) wrap.classList.add( 'wl-updating' );

        var fd = new FormData();
        fd.append( 'action',      'wl_cart_remove_coupon' );
        fd.append( 'nonce',       NONCE );
        fd.append( 'coupon_code', code );

        fetch( AJAX_URL, { method: 'POST', body: fd, credentials: 'same-origin' } )
            .then( function ( r ) { return r.json(); } )
            .then( function ( res ) {
                var noticesHtml = ( res.data && res.data.notices_html ) ? res.data.notices_html : '';
                refreshSections( noticesHtml );
            } )
            .catch( function () {
                if ( wrap ) wrap.classList.remove( 'wl-updating' );
            } );
    } );

    // ── Remove button click ──────────────────────────────────────────────────
    // Intercept before the browser navigates to the WC remove URL.
    // qty = 0 triggers WC()->cart->remove_cart_item() which also stores the
    // item in removed_cart_contents so the undo link works.
    document.addEventListener( 'click', function ( e ) {
        var removeBtn = e.target.closest( '.wl-cart-item__remove' );
        if ( ! removeBtn || ! removeBtn.closest( TABLE_SEL ) ) return;

        e.preventDefault();

        var article = removeBtn.closest( '.wl-cart-item' );
        if ( ! article ) return;

        var key = article.dataset.key || removeBtn.dataset.cart_item_key;
        if ( ! key ) return;

        article.classList.add( 'wl-cart-item--updating' );
        ajaxUpdateQty( key, 0 );
    } );

    // ── Stepper +/− button click ─────────────────────────────────────────────
    document.addEventListener( 'click', function ( e ) {
        var btn = e.target.closest( '.wl-qty-stepper__btn' );
        if ( ! btn || ! btn.closest( TABLE_SEL ) ) return;

        var stepper = btn.closest( '.wl-qty-stepper' );
        var input   = stepper ? stepper.querySelector( 'input.qty' ) : null;
        if ( ! input ) return;

        var val  = parseInt( input.value, 10 ) || 1;
        var step = parseInt( btn.dataset.step, 10 ) || 1;
        var min  = parseInt( btn.dataset.min, 10 );
        var max  = parseInt( btn.dataset.max, 10 );

        if ( btn.classList.contains( 'wl-qty-stepper__btn--minus' ) ) {
            val = isNaN( min ) ? Math.max( 0, val - step ) : Math.max( min, val - step );
        } else {
            val = isNaN( max ) ? val + step : Math.min( max, val + step );
        }

        input.value = val;
        input.dispatchEvent( new Event( 'change', { bubbles: true } ) );
    } );

    // ── Quantity input change → debounced AJAX update ────────────────────────
    document.addEventListener( 'change', function ( e ) {
        var input = e.target.closest( 'input.qty' );
        if ( ! input || ! input.closest( TABLE_SEL ) ) return;

        var article = input.closest( '.wl-cart-item' );
        var key     = article ? article.dataset.key : null;
        if ( ! key ) return;

        var qty = Math.max( 0, parseInt( input.value, 10 ) || 0 );

        clearTimeout( timers[ key ] );
        article.classList.add( 'wl-cart-item--updating' );

        timers[ key ] = setTimeout( function () {
            ajaxUpdateQty( key, qty );
        }, 400 );
    } );

    // ── AJAX — update quantity on server ─────────────────────────────────────
    function ajaxUpdateQty( key, qty ) {
        var fd = new FormData();
        fd.append( 'action', 'wl_cart_page_update_qty' );
        fd.append( 'nonce',         NONCE );
        fd.append( 'cart_item_key', key );
        fd.append( 'qty',           qty );

        fetch( AJAX_URL, { method: 'POST', body: fd, credentials: 'same-origin' } )
            .then( function ( r ) { return r.json(); } )
            .then( function ( res ) {
                if ( ! res.success ) {
                    clearLoading();
                    return;
                }

                if ( res.data && res.data.cart_empty ) {
                    // Redirect with ?removed_item=1 so WC's clean_up_removed_cart_contents()
                    // skips wiping the session — otherwise the undo link breaks.
                    window.location.href = window.location.pathname + '?removed_item=1';
                } else {
                    // notices_html is pre-captured in PHP before the theme can
                    // consume the session notice; pass it through to refreshSections.
                    var noticesHtml = ( res.data && res.data.notices_html ) ? res.data.notices_html : '';
                    refreshSections( noticesHtml );
                }
            } )
            .catch( clearLoading );
    }

    // ── Re-fetch page, swap cart table + cart total in-place ─────────────────
    function refreshSections( noticesHtml ) {
        // Include ?removed_item=1 so WC's clean_up_removed_cart_contents() skips
        // wiping removed_cart_contents — this preserves the undo link session data.
        var fetchUrl = window.location.pathname + '?removed_item=1';
        fetch( fetchUrl, { credentials: 'same-origin' } )
            .then( function ( r ) { return r.text(); } )
            .then( function ( html ) {
                var doc = ( new DOMParser() ).parseFromString( html, 'text/html' );

                replaceNode( TABLE_SEL, doc );
                replaceNode( TOTAL_SEL, doc );

                if ( noticesHtml ) {
                    // Inject the pre-captured notice HTML directly — the re-fetched page
                    // won't have it because wc_print_notices() already cleared the session.
                    injectNotices( noticesHtml );
                } else {
                    // For non-removal updates (qty change): pick up any notices the
                    // re-fetched page rendered inside .woocommerce-notices-wrapper.
                    var newNotices = doc.querySelector( '.woocommerce-notices-wrapper' );
                    var curNotices = document.querySelector( '.woocommerce-notices-wrapper' );

                    if ( newNotices && curNotices ) {
                        curNotices.outerHTML = newNotices.outerHTML;
                    } else if ( newNotices ) {
                        var table = document.querySelector( TABLE_SEL );
                        if ( table ) {
                            table.insertAdjacentHTML( 'beforebegin', newNotices.outerHTML );
                        }
                    }
                }

                // Notify WooCommerce: refreshes mini-cart, header cart count, etc.
                if ( window.jQuery ) {
                    jQuery( document.body ).trigger( 'wc_fragment_refresh' );
                    jQuery( document.body ).trigger( 'updated_cart_totals' );
                }
            } )
            .catch( clearLoading );
    }

    // ── Inject a notices HTML block into the page ────────────────────────────
    function injectNotices( html ) {
        if ( ! html ) return;
        var curNotices = document.querySelector( '.woocommerce-notices-wrapper' );
        if ( curNotices ) {
            curNotices.outerHTML = html;
        } else {
            var table = document.querySelector( TABLE_SEL );
            if ( table ) {
                table.insertAdjacentHTML( 'beforebegin', html );
            }
        }
    }

    function replaceNode( selector, newDoc ) {
        var cur = document.querySelector( selector );
        var nxt = newDoc.querySelector( selector );
        if ( cur && nxt ) cur.outerHTML = nxt.outerHTML;
    }

    function clearLoading() {
        document.querySelectorAll( '.wl-cart-item--updating' ).forEach( function ( el ) {
            el.classList.remove( 'wl-cart-item--updating' );
        } );
        document.querySelectorAll( TOTAL_SEL ).forEach( function ( el ) {
            el.classList.remove( 'wl-updating' );
        } );
    }

} )();
