/**
 * TitanCart — Subscribe Popup (Phase 5 block B, S241)
 *
 * Self-contained newsletter signup modal. Config arrives via the localized
 * window.titancartSubscribePopup object (see StorefrontModule::enqueue_assets). The
 * popup builds its own DOM, fires on a time delay and/or exit intent, posts to
 * the public /subscribe endpoint enrolling into the admin-chosen list
 * (source 'popup'), and suppresses itself for N days after a dismiss or a
 * successful signup via localStorage.
 *
 * No build step — plain ES5 to match the rest of assets/js.
 */
(function () {
    'use strict';

    var cfg = window.titancartSubscribePopup;
    // Nothing to do without config, an API base, or a chosen list.
    if ( ! cfg || ! cfg.apiUrl || ! cfg.listId ) { return; }

    var STORE_KEY = 'tc_subpop';
    var DAY_MS    = 86400000;
    var shown     = false;
    var armed     = false;
    var timeTimer = null;
    var overlayEl = null;
    var lastFocus = null;

    // ── Suppression window ──────────────────────────────────────────────────
    function suppressed() {
        try {
            var raw = window.localStorage.getItem( STORE_KEY );
            if ( ! raw ) { return false; }
            var data = JSON.parse( raw );
            if ( ! data || ! data.t ) { return false; }
            var days = parseInt( cfg.frequencyDays, 10 );
            if ( isNaN( days ) || days < 0 ) { days = 30; }
            if ( days === 0 ) { return false; } // 0 = always show
            return ( Date.now() - data.t ) < ( days * DAY_MS );
        } catch ( e ) {
            return false;
        }
    }

    function remember() {
        try {
            window.localStorage.setItem( STORE_KEY, JSON.stringify( { t: Date.now() } ) );
        } catch ( e ) { /* private mode / quota — ignore */ }
    }

    // Exit intent is unreliable on touch devices — fall back to the time delay.
    function isTouch() {
        return ( 'ontouchstart' in window ) ||
               ( navigator.maxTouchPoints > 0 ) ||
               ( navigator.msMaxTouchPoints > 0 );
    }

    function esc( s ) {
        return String( s == null ? '' : s )
            .replace( /&/g, '&amp;' ).replace( /</g, '&lt;' ).replace( />/g, '&gt;' )
            .replace( /"/g, '&quot;' ).replace( /'/g, '&#039;' );
    }

    // ── Modal teardown ──────────────────────────────────────────────────────
    function onKeydown( e ) {
        if ( e.key === 'Escape' || e.keyCode === 27 ) { close( true ); }
    }

    function close( setSuppress ) {
        if ( setSuppress ) { remember(); }
        if ( overlayEl && overlayEl.parentNode ) {
            overlayEl.parentNode.removeChild( overlayEl );
        }
        overlayEl = null;
        document.removeEventListener( 'keydown', onKeydown );
        if ( lastFocus && lastFocus.focus ) { try { lastFocus.focus(); } catch ( e ) {} }
    }

    // ── Modal build ─────────────────────────────────────────────────────────
    function build() {
        lastFocus = document.activeElement;

        var overlay = document.createElement( 'div' );
        overlay.className = 'tc-subpop-overlay';
        overlay.setAttribute( 'role', 'dialog' );
        overlay.setAttribute( 'aria-modal', 'true' );
        overlay.setAttribute( 'aria-label', cfg.heading || 'Subscribe' );

        var card = document.createElement( 'div' );
        card.className = 'tc-subpop-card';
        card.innerHTML =
            '<button type="button" class="tc-subpop-close" aria-label="Close">&times;</button>' +
            '<h2 class="tc-subpop-heading">' + esc( cfg.heading || 'Subscribe' ) + '</h2>' +
            '<p class="tc-subpop-text">' + esc( cfg.text || '' ) + '</p>' +
            '<div class="tc-subpop-form">' +
                '<input type="email" class="tc-subpop-input" autocomplete="email" ' +
                    'placeholder="' + esc( cfg.placeholder || 'Enter your email' ) + '" />' +
                '<button type="button" class="tc-subpop-btn">' + esc( cfg.button || 'Subscribe' ) + '</button>' +
            '</div>' +
            '<div class="tc-subpop-msg" role="status" aria-live="polite"></div>';

        overlay.appendChild( card );
        document.body.appendChild( overlay );
        overlayEl = overlay;

        var input    = card.querySelector( '.tc-subpop-input' );
        var btn      = card.querySelector( '.tc-subpop-btn' );
        var msgEl    = card.querySelector( '.tc-subpop-msg' );
        var closeBtn = card.querySelector( '.tc-subpop-close' );
        var formEl   = card.querySelector( '.tc-subpop-form' );

        function showMsg( text, kind ) {
            msgEl.textContent = text;
            msgEl.className = 'tc-subpop-msg tc-subpop-msg--' + ( kind || 'info' );
        }

        function submit() {
            var email = ( input.value || '' ).trim();
            if ( ! email || email.indexOf( '@' ) === -1 ) {
                showMsg( 'Please enter a valid email address.', 'error' );
                input.focus();
                return;
            }
            btn.disabled   = true;
            input.disabled = true;
            showMsg( '', 'info' );

            fetch( cfg.apiUrl + '/subscribe', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
                credentials: 'same-origin',
                body: JSON.stringify( {
                    email: email,
                    list_ids: [ parseInt( cfg.listId, 10 ) ],
                    source: 'popup'
                } )
            } ).then( function ( res ) {
                return res.json().then( function ( data ) {
                    return { ok: res.ok, data: data };
                } ).catch( function () {
                    return { ok: res.ok, data: {} };
                } );
            } ).then( function ( r ) {
                if ( r.ok && r.data && r.data.subscribed ) {
                    remember(); // a successful signup suppresses future shows
                    if ( formEl ) { formEl.style.display = 'none'; }
                    showMsg( r.data.message || 'Thanks for subscribing!', 'success' );
                    setTimeout( function () { close( false ); }, 2500 );
                } else {
                    var err = ( r.data && r.data.message )
                        ? r.data.message
                        : 'Something went wrong. Please try again.';
                    showMsg( err, 'error' );
                    btn.disabled   = false;
                    input.disabled = false;
                }
            } ).catch( function () {
                showMsg( 'Network error. Please try again.', 'error' );
                btn.disabled   = false;
                input.disabled = false;
            } );
        }

        btn.addEventListener( 'click', submit );
        input.addEventListener( 'keydown', function ( e ) {
            if ( e.key === 'Enter' || e.keyCode === 13 ) { e.preventDefault(); submit(); }
        } );
        closeBtn.addEventListener( 'click', function () { close( true ); } );
        overlay.addEventListener( 'click', function ( e ) {
            if ( e.target === overlay ) { close( true ); }
        } );
        document.addEventListener( 'keydown', onKeydown );

        setTimeout( function () { try { input.focus(); } catch ( e ) {} }, 50 );
    }

    // ── Trigger orchestration ────────────────────────────────────────────────
    function trigger() {
        if ( shown ) { return; }
        if ( suppressed() ) { return; }
        shown = true;
        disarm();
        build();
    }

    function onMouseOut( e ) {
        // Exit intent: cursor leaves the viewport toward the top (browser chrome).
        if ( e.clientY <= 0 && ! e.relatedTarget && ! e.toElement ) { trigger(); }
    }

    function disarm() {
        armed = false;
        if ( timeTimer ) { clearTimeout( timeTimer ); timeTimer = null; }
        document.removeEventListener( 'mouseout', onMouseOut );
    }

    function arm() {
        if ( armed || shown || suppressed() ) { return; }
        armed = true;

        var mode  = cfg.trigger || 'both';
        var touch = isTouch();
        var delay = parseInt( cfg.delay, 10 );
        if ( isNaN( delay ) || delay < 0 ) { delay = 15; }

        // On touch devices exit intent can't fire — always use the time fallback.
        var useTime = ( mode === 'time' || mode === 'both' || touch );
        var useExit = ( mode === 'exit' || mode === 'both' ) && ! touch;

        if ( useTime ) { timeTimer = setTimeout( trigger, delay * 1000 ); }
        if ( useExit ) { document.addEventListener( 'mouseout', onMouseOut ); }
    }

    function init() {
        if ( suppressed() ) { return; }
        arm();
    }

    if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', init );
    } else {
        init();
    }
})();
