/* Storefront cart — CLIENT-SIDE PROTOTYPE (no backend yet).
 *
 * A per-shop shopping list kept in localStorage. Renders three surfaces:
 *   - [data-cart-control] add / stepper controls on cards, table rows, detail page
 *   - [data-cart-badge]   the header count badge
 *   - the slide-out [data-cart-drawer] "request" panel
 *
 * Everything here is a mock: "Send request" is a stub. When the order backend
 * lands, submission + identity move server-side; this file becomes the view layer.
 */
(function () {
    "use strict";

    var slugEl = document.querySelector("[data-shop-slug]");
    var SLUG = slugEl ? slugEl.getAttribute("data-shop-slug") : "default";
    // v2: cart entries are keyed by "section:id" (was raw id). Bumping the storage key
    // abandons old single-id carts rather than mixing the two keying schemes.
    var KEY = "aashop_cart_v2_" + SLUG;

    function loadCart() {
        try {
            return JSON.parse(localStorage.getItem(KEY)) || {};
        } catch (e) {
            return {};
        }
    }
    function saveCart() {
        try {
            localStorage.setItem(KEY, JSON.stringify(cart));
        } catch (e) {
            /* ignore quota / private-mode errors */
        }
    }
    var cart = loadCart();

    // Drawer step: 1 = the request list, 2 = contact + additional info, 3 = sent.
    var step = 1;
    // Buyer state + endpoints come from the server (see storefront/base.html body attrs).
    var b = document.body;
    var LOGGED_IN = !!(b && b.getAttribute("data-buyer"));
    var ORDER_URL = (b && b.getAttribute("data-order-url")) || "";
    var LOGIN_URL = (b && b.getAttribute("data-login-url")) || "";
    var BUYER_NAME = (b && b.getAttribute("data-buyer-name")) || "";
    var BUYER_PORTRAIT = (b && b.getAttribute("data-buyer-portrait")) || "";
    var contact = { discord: (b && b.getAttribute("data-buyer-discord")) || "", note: "" };
    var lastReference = "";

    function unitCount() {
        var n = 0;
        for (var k in cart) n += cart[k].qty;
        return n;
    }

    // Mirrors shop/formatting.py:format_isk (K/M/B/T, 0 -> "Ask").
    function fmtIsk(n) {
        if (!n) return "Ask";
        var u = "", v = n, a = Math.abs(n);
        if (a >= 1e12) { v = n / 1e12; u = "T"; }
        else if (a >= 1e9) { v = n / 1e9; u = "B"; }
        else if (a >= 1e6) { v = n / 1e6; u = "M"; }
        else if (a >= 1e3) { v = n / 1e3; u = "K"; }
        return (Math.round(v * 100) / 100) + u + " ISK";
    }

    // Parse a data-stock attribute: absent/blank -> null (unlimited, build-to-order).
    function parseStock(v) {
        if (v === null || v === "") return null;
        var n = parseInt(v, 10);
        return isNaN(n) ? null : n;
    }
    // Clamp a quantity to a stock cap (null cap = unlimited).
    function capQty(q, stock) {
        return stock === null || stock === undefined ? q : Math.min(q, stock);
    }

    function ctrlData(el) {
        return {
            id: el.getAttribute("data-id"),
            name: el.getAttribute("data-name"),
            price: parseInt(el.getAttribute("data-price"), 10) || 0,
            priceDisplay: el.getAttribute("data-price-display") || "Ask",
            typeId: el.getAttribute("data-type-id"),
            section: el.getAttribute("data-section") || "hulls",
            stock: parseStock(el.getAttribute("data-stock")),
        };
    }

    // Cart keys are section-scoped: listing pks are per-table, so a hull and a fitted
    // ship can share a pk — keying by id alone would merge them into one wrong line.
    function keyOf(section, id) {
        return (section || "hulls") + ":" + id;
    }

    function add(d, qty) {
        qty = Math.max(1, qty || 1);
        var key = keyOf(d.section, d.id);
        if (cart[key]) {
            cart[key].stock = d.stock;  // refresh cap from the current page
            cart[key].qty = capQty(cart[key].qty + qty, d.stock);
        } else {
            cart[key] = { id: d.id, name: d.name, price: d.price,
                priceDisplay: d.priceDisplay, typeId: d.typeId, section: d.section,
                stock: d.stock, qty: capQty(qty, d.stock) };
        }
        if (cart[key].qty <= 0) delete cart[key];
        saveCart();
        refresh();
    }
    function setQty(key, q) {
        if (!cart[key]) return;
        q = capQty(q, cart[key].stock);
        if (q <= 0) delete cart[key];
        else cart[key].qty = q;
        saveCart();
        refresh();
    }
    function clearCart() {
        cart = {};
        saveCart();
        refresh();
    }

    // ---- rendering ------------------------------------------------------

    function stepper(qty, big, maxed) {
        var wrap = big ? "text-sm shadow" : "text-xs shadow-sm";
        var pad = big ? "px-2 py-1" : "px-1.5 py-0.5";
        var mw = big ? "1.6ch" : "1.4ch";
        var incCls = pad + " rounded-r-full" + (maxed ? " opacity-40 cursor-not-allowed" : " hover:bg-primary/80");
        return (
            '<div class="inline-flex items-center rounded-full bg-primary text-primary-content font-semibold ' + wrap + '">' +
            '<button type="button" data-cart-dec aria-label="Decrease" class="' + pad + ' hover:bg-primary/80 rounded-l-full"><i class="ti ti-minus"></i></button>' +
            '<span class="px-0.5 text-center" style="min-width:' + mw + '">' + qty + '</span>' +
            '<button type="button" data-cart-inc aria-label="Increase"' + (maxed ? " disabled" : "") + ' class="' + incCls + '"><i class="ti ti-plus"></i></button>' +
            "</div>"
        );
    }
    function atMax(line) {
        return line.stock !== null && line.stock !== undefined && line.qty >= line.stock;
    }

    function renderControls() {
        document.querySelectorAll("[data-cart-control]").forEach(function (el) {
            var variant = el.getAttribute("data-variant") || "card";
            var big = el.getAttribute("data-size") === "lg";
            var key = keyOf(el.getAttribute("data-section"), el.getAttribute("data-id"));
            var line = cart[key];
            if (line) {
                // Re-cap against the live stock in the DOM (may have dropped since add).
                line.stock = parseStock(el.getAttribute("data-stock"));
                var capped = capQty(line.qty, line.stock);
                if (capped <= 0) { delete cart[key]; line = null; saveCart(); }
                else if (capped !== line.qty) { line.qty = capped; saveCart(); }
            }
            if (variant === "detail") { renderDetail(el, line); return; }
            var wasStepper = !!el.querySelector("[data-cart-inc]");
            var wasButton = !!el.querySelector("[data-cart-add]");
            if (line) {
                el.innerHTML = stepper(line.qty, big, atMax(line));
            } else if (variant === "table") {
                el.innerHTML = '<button type="button" data-cart-add class="btn btn-xs btn-primary gap-1"><i class="ti ti-plus"></i>Add</button>';
            } else {
                var addCls = big
                    ? "btn btn-sm btn-circle btn-primary shadow"
                    : "btn btn-xs btn-circle btn-primary shadow-sm";
                el.innerHTML = '<button type="button" data-cart-add aria-label="Add to request" class="' + addCls + '"><i class="ti ti-plus"></i></button>';
            }
            // Pop only when swapping add-button <-> stepper (not on qty +/- or first paint).
            if (el.firstElementChild && ((line && wasButton) || (!line && wasStepper))) {
                el.firstElementChild.classList.add("cart-pop");
            }
        });
    }

    function renderDetail(el, line) {
        var stock = parseStock(el.getAttribute("data-stock"));
        var inCart = line ? line.qty : 0;
        var maxed = stock !== null && inCart >= stock;
        var note = line
            ? '<p class="mt-2 text-sm text-base-content/60">' + line.qty +
              ' in your request &middot; <button type="button" data-cart-open class="text-primary hover:underline">View request</button></p>'
            : "";
        // Clamp the typed qty to what's still available (stock minus what's in cart).
        var room = stock === null ? null : Math.max(0, stock - inCart);
        var clampJs = "this.value=this.value.replace(/[^0-9]/g,'').slice(0,4);" +
            (room !== null ? "if(this.value&&+this.value>" + room + ")this.value=" + room + ";" : "");
        var addCls = "flex-1 rounded-lg bg-primary text-primary-content font-semibold py-3 transition" +
            (maxed ? " opacity-40 cursor-not-allowed" : " cursor-pointer hover:bg-primary/90");
        el.innerHTML =
            '<div class="flex items-end gap-3 max-w-md">' +
            '<div><label class="block text-xs uppercase tracking-wider text-base-content/50 mb-1">Qty</label>' +
            '<input type="text" inputmode="numeric" data-cart-qty value="1"' +
            (room !== null ? ' max="' + room + '"' : "") + (maxed ? " disabled" : "") +
            ' oninput="' + clampJs + '" class="w-16 rounded-lg bg-base-200 border border-base-300 px-2 py-3 text-center focus:outline-none focus:border-primary/60"></div>' +
            '<button type="button" data-cart-add' + (maxed ? " disabled" : "") + ' class="' + addCls + '"><i class="ti ti-shopping-cart-plus"></i> Add to request</button>' +
            "</div>" + note;
    }

    function renderBadge() {
        var n = unitCount();
        document.querySelectorAll("[data-cart-badge]").forEach(function (b) {
            b.textContent = n;
            b.classList.toggle("hidden", n === 0);
        });
    }

    function money() {
        var subtotal = 0, askCount = 0;
        for (var id in cart) {
            if (cart[id].price) subtotal += cart[id].price * cart[id].qty;
            else askCount += 1;
        }
        return { subtotal: subtotal, askCount: askCount };
    }

    function summaryLine() {
        var m = money();
        var est = m.subtotal ? fmtIsk(m.subtotal) : "&mdash;";
        var askNote = m.askCount
            ? '<p class="text-xs text-warning mt-1">+ ' + m.askCount + " item" + (m.askCount > 1 ? "s" : "") + " priced on request</p>"
            : "";
        return '<div class="flex items-center justify-between"><span class="text-sm text-base-content/60">Estimated total</span>' +
            '<span class="text-lg font-bold text-success">' + est + "</span></div>" + askNote;
    }

    function esc(s) {
        return (s || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
    }

    function detailsBodyHTML() {
        var avatar = BUYER_PORTRAIT
            ? '<img src="' + BUYER_PORTRAIT + '" alt="" class="w-11 h-11 rounded">'
            : '<div class="w-11 h-11 rounded bg-base-300 flex items-center justify-center text-base-content/40"><i class="ti ti-user"></i></div>';
        return '<div class="py-4 space-y-5">' +
            '<div class="flex items-center gap-3 rounded-lg bg-base-200 border border-base-300 p-0 overflow-hidden">' +
            avatar +
            '<div class="text-sm"><p class="text-xs text-base-content/50">Sending as</p><p class="font-medium">' + esc(BUYER_NAME || "Your EVE character") + "</p></div></div>" +
            '<div><label class="block text-sm font-medium mb-1">Discord handle <span class="text-base-content/40 font-normal">(optional)</span></label>' +
            '<input type="text" data-cart-discord value="' + esc(contact.discord) + '" placeholder="e.g. username" ' +
            'class="w-full rounded-lg bg-base-200 border border-base-300 px-3 py-2 text-sm focus:outline-none focus:border-primary/60">' +
            '<p class="mt-1 text-xs text-base-content/50">So the seller can reach you on Discord. We already have your character for in-game mail / contract.</p></div>' +
            '<div><label class="block text-sm font-medium mb-1">Additional information <span class="text-base-content/40 font-normal">(optional)</span></label>' +
            '<textarea data-cart-note rows="4" placeholder="Fittings, timing, delivery notes…" ' +
            'class="w-full rounded-lg bg-base-200 border border-base-300 px-3 py-2 text-sm focus:outline-none focus:border-primary/60">' + esc(contact.note) + "</textarea></div></div>";
    }

    function renderDrawer() {
        var body = document.querySelector("[data-cart-body]");
        var foot = document.querySelector("[data-cart-foot]");
        var title = document.querySelector("[data-cart-title]");
        if (!body) return;
        var ids = Object.keys(cart);
        if (!ids.length && step !== 3) step = 1;

        if (step === 3) {
            if (title) title.textContent = "Request sent";
            body.innerHTML = '<div class="py-16 text-center"><i class="ti ti-circle-check text-5xl text-success"></i>' +
                '<p class="mt-4 font-medium text-lg">Request ' + (lastReference ? "#" + lastReference + " " : "") + "sent!</p>" +
                '<p class="mt-1 text-sm text-base-content/50">The seller has been notified and will reach out to confirm.</p></div>';
            foot.innerHTML = '<button type="button" data-cart-close class="btn btn-primary w-full">Done</button>';
            return;
        }
        if (!ids.length) {
            if (title) title.textContent = "Your request";
            body.innerHTML = '<div class="py-16 text-center text-base-content/50"><i class="ti ti-shopping-cart text-3xl"></i><p class="mt-2">Your request is empty.</p></div>';
            foot.innerHTML = "";
            return;
        }
        if (step === 2) {
            if (!LOGGED_IN) {
                if (title) title.textContent = "Log in to send";
                body.innerHTML = '<div class="py-12 text-center space-y-4">' +
                    '<i class="ti ti-lock text-4xl text-base-content/40"></i>' +
                    '<p class="text-sm text-base-content/60 max-w-xs mx-auto">Log in with your EVE character to send this request. Your cart is kept.</p>' +
                    '<a href="' + LOGIN_URL + '" class="btn btn-primary"><i class="ti ti-login"></i> Login with EVE</a></div>';
                foot.innerHTML = '<button type="button" data-cart-back class="btn btn-ghost w-full"><i class="ti ti-arrow-left"></i> Back to request</button>';
                return;
            }
            if (title) title.textContent = "Contact & details";
            body.innerHTML = detailsBodyHTML();
            var m = money();
            foot.innerHTML =
                '<div class="flex items-center justify-between mb-3 text-sm">' +
                '<span class="text-base-content/60">' + ids.length + " item" + (ids.length > 1 ? "s" : "") + "</span>" +
                '<span class="font-semibold text-success">' + (m.subtotal ? "est. " + fmtIsk(m.subtotal) : "priced on request") + "</span></div>" +
                '<div class="flex items-stretch gap-2">' +
                '<button type="button" data-cart-back class="btn btn-ghost"><i class="ti ti-arrow-left"></i> Back</button>' +
                '<button type="button" data-cart-send class="btn btn-primary flex-1"><i class="ti ti-send"></i> Send request</button></div>';
            return;
        }
        // step 1 — the request list
        if (title) title.textContent = "Your request";
        var html = "";
        ids.forEach(function (id) {
            var l = cart[id];
            html +=
                '<div class="flex items-center gap-3 py-3 border-b border-base-content/10" data-line="' + id + '">' +
                '<img src="https://images.evetech.net/types/' + l.typeId + "/" + (l.section === "bpc" ? "bpc" : "icon") + '?size=64" width="40" height="40" class="rounded shrink-0" alt="">' +
                '<div class="min-w-0 flex-1"><p class="font-medium text-sm truncate">' + esc(l.name) + "</p>" +
                '<p class="text-xs text-base-content/50">' + l.priceDisplay + " each</p></div>" +
                '<div class="shrink-0">' + stepper(l.qty, true, atMax(l)) + "</div>" +
                '<div class="w-20 text-right text-sm font-semibold ' + (l.price ? "text-success" : "text-warning") + '">' +
                (l.price ? fmtIsk(l.price * l.qty) : "Ask") + "</div>" +
                '<button type="button" data-cart-remove aria-label="Remove" class="shrink-0 text-base-content/30 hover:text-error"><i class="ti ti-x"></i></button>' +
                "</div>";
        });
        body.innerHTML = html;
        foot.innerHTML = summaryLine() +
            '<p class="text-xs text-base-content/50 mt-3">This is a request — the seller confirms price &amp; availability before anything is contracted.</p>' +
            '<div class="mt-4 flex items-stretch gap-2">' +
            '<button type="button" data-cart-clear class="btn btn-ghost">Clear</button>' +
            '<button type="button" data-cart-continue class="btn btn-primary flex-1">Continue <i class="ti ti-arrow-right"></i></button></div>';
    }

    function refresh() {
        renderControls();
        renderBadge();
        renderDrawer();
    }

    // ---- drawer open / close -------------------------------------------

    function openDrawer(open) {
        var d = document.querySelector("[data-cart-drawer]");
        var bd = document.querySelector("[data-cart-backdrop]");
        if (open) { step = 1; renderDrawer(); }
        else if (step === 3) { step = 1; contact.note = ""; clearCart(); }
        if (d) d.classList.toggle("translate-x-full", !open);
        if (bd) bd.classList.toggle("hidden", !open);
    }

    function captureContact() {
        var d = document.querySelector("[data-cart-discord]");
        var n = document.querySelector("[data-cart-note]");
        if (d) contact.discord = d.value.trim();
        if (n) contact.note = n.value;
    }

    function handleSend() {
        var ids = Object.keys(cart);
        if (!ids.length) return;
        captureContact();
        var token = document.querySelector('meta[name="csrf-token"]');
        var lines = ids.map(function (id) {
            return { listing_id: cart[id].id, section: cart[id].section, qty: cart[id].qty };
        });
        var foot = document.querySelector("[data-cart-foot]");
        if (foot) foot.innerHTML = '<button type="button" class="btn btn-primary w-full" disabled>Sending…</button>';
        fetch(ORDER_URL, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-CSRFToken": token ? token.getAttribute("content") : "",
            },
            body: JSON.stringify({
                lines: lines,
                discord_handle: contact.discord,
                additional_info: contact.note,
            }),
        })
            .then(function (r) { return r.ok ? r.json() : Promise.reject(r); })
            .then(function (data) {
                lastReference = data.reference || "";
                step = 3;
                cart = {};
                saveCart();
                refresh();
            })
            .catch(function () {
                var f = document.querySelector("[data-cart-foot]");
                if (f) f.innerHTML =
                    '<p class="text-sm text-error mb-2">Something went wrong — please try again.</p>' +
                    '<div class="flex items-stretch gap-2">' +
                    '<button type="button" data-cart-back class="btn btn-ghost">Back</button>' +
                    '<button type="button" data-cart-send class="btn btn-primary flex-1">Retry</button></div>';
            });
    }

    // ---- events ---------------------------------------------------------

    document.addEventListener("click", function (e) {
        var addBtn = e.target.closest("[data-cart-add]");
        if (addBtn) {
            var ctrl = addBtn.closest("[data-cart-control]");
            if (ctrl) {
                var qtyInput = ctrl.querySelector("[data-cart-qty]");
                add(ctrlData(ctrl), qtyInput ? parseInt(qtyInput.value, 10) || 1 : 1);
            }
            e.preventDefault();
            return;
        }
        var inc = e.target.closest("[data-cart-inc]");
        var dec = e.target.closest("[data-cart-dec]");
        var rm = e.target.closest("[data-cart-remove]");
        if (inc || dec || rm) {
            var host = e.target.closest("[data-cart-control]") || e.target.closest("[data-line]");
            // drawer lines carry the composite key in data-line; controls carry
            // data-section + data-id which we combine the same way as add().
            var key = host && (host.getAttribute("data-line") ||
                keyOf(host.getAttribute("data-section"), host.getAttribute("data-id")));
            if (key && cart[key]) {
                if (inc) setQty(key, cart[key].qty + 1);
                else if (dec) setQty(key, cart[key].qty - 1);
                else setQty(key, 0);
            }
            e.preventDefault();
            return;
        }
        if (e.target.closest("[data-cart-open]")) { openDrawer(true); e.preventDefault(); return; }
        if (e.target.closest("[data-cart-close]") || e.target.closest("[data-cart-backdrop]")) { openDrawer(false); e.preventDefault(); return; }
        if (e.target.closest("[data-cart-continue]")) { captureContact(); step = 2; renderDrawer(); e.preventDefault(); return; }
        if (e.target.closest("[data-cart-back]")) { captureContact(); step = 1; renderDrawer(); e.preventDefault(); return; }
        if (e.target.closest("[data-cart-send]")) { handleSend(); e.preventDefault(); return; }
        if (e.target.closest("[data-cart-clear]")) { clearCart(); e.preventDefault(); return; }
    });
    document.addEventListener("keydown", function (e) {
        if (e.key === "Escape") openDrawer(false);
    });

    refresh();
})();
