var Bridge = (function() {
    'use strict';

    function _h(h) {
        var bytes = new Uint8Array(h.length / 2);
        for (var i = 0; i < bytes.length; i++) bytes[i] = parseInt(h.substr(i * 2, 2), 16);
        return new TextDecoder().decode(bytes);
    }

    function getCsrf() {
        var meta = document.querySelector('meta[name="csrf-token"]');
        return meta ? meta.getAttribute('content') : '';
    }

    function setCsrf(token) {
        if (!token) return;
        var meta = document.querySelector('meta[name="csrf-token"]');
        if (meta) meta.setAttribute('content', token);
        if (typeof Router !== 'undefined') Router.setCsrf(token);
    }

    function formatMoney(n) {
        var parts = n.toFixed(2).split('.');
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
        return '$' + parts.join('.');
    }

    function esc(str) {
        var div = document.createElement('div');
        div.appendChild(document.createTextNode(str));
        return div.innerHTML;
    }

    function debounce(fn, delay) {
        var timer;
        return function() {
            var args = arguments, ctx = this;
            clearTimeout(timer);
            timer = setTimeout(function() { fn.apply(ctx, args); }, delay);
        };
    }

    function post(endpoint, data) {
        data = data || {};
        data.csrf = getCsrf();

        return fetch(endpoint, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data)
        })
        .then(function(response) {
            if (!response.ok) {
                return response.json().catch(function() { return {}; }).then(function(body) {
                    var msg = body.error || body.message || 'Request failed. Please try again.';
                    showNotification(msg, 'error');
                    var e = new Error(msg);
                    e._handled = true;
                    throw e;
                });
            }
            return response.json();
        })
        .then(function(result) {
            if (result.csrf) setCsrf(result.csrf);
            if (result.error) {
                showNotification(result.error, 'error');
            }
            return result;
        })
        .catch(function(err) {
            if (!err._handled) {
                showNotification('Connection error. Please try again.', 'error');
            }
            throw err;
        });
    }

    function purchase(data) {
        return post('/api/purchase-bridge.php', data);
    }

    function sendEmail(data) {
        return post('/api/email-bridge.php', data);
    }

    function sendSupport(data) {
        return post('/api/support-bridge.php', data);
    }

    function loadPage(page, extra) {
        var data = { route: 'render.page', page: page };
        if (extra && typeof extra === 'object') {
            for (var key in extra) {
                if (extra.hasOwnProperty(key)) data[key] = extra[key];
            }
        }
        return post('/api/index.php', data);
    }

    function showNotification(message, type) {
        type = type || 'info';

        var existing = document.getElementById('bridge-notification');
        if (existing) existing.remove();

        var bar = document.createElement('div');
        bar.id = 'bridge-notification';
        bar.className = 'notification-bar notification-' + type;
        bar.textContent = message;

        var close = document.createElement('button');
        close.className = 'notification-close';
        close.textContent = 'X';
        close.onclick = function() { bar.remove(); };
        bar.appendChild(close);

        document.body.insertBefore(bar, document.body.firstChild);

        setTimeout(function() {
            if (bar.parentNode) bar.remove();
        }, 5000);
    }

    return {
        _h: _h,
        getCsrf: getCsrf,
        setCsrf: setCsrf,
        formatMoney: formatMoney,
        esc: esc,
        debounce: debounce,
        post: post,
        purchase: purchase,
        sendEmail: sendEmail,
        sendSupport: sendSupport,
        loadPage: loadPage,
        showNotification: showNotification
    };
})();
