import http from "k6/http";
import { check, sleep, group } from "k6";
import { Counter, Trend } from "k6/metrics";

// ---------------- Configuration ----------------
export const options = {
    // Adjust vus/duration for your environment
    scenarios: {
        steady_mutations: {
            executor: "constant-vus",
            vus: __ENV.VUS ? parseInt(__ENV.VUS, 10) : 20,
            duration: __ENV.DURATION || "5m",
            gracefulStop: "30s",
        },
        ramp_up: {
            executor: "ramping-vus",
            startVUs: 0,
            stages: [
                {
                    duration: "1m",
                    target: __ENV.RAMP_TARGET
                        ? parseInt(__ENV.RAMP_TARGET, 10)
                        : 50,
                },
                {
                    duration: "1m",
                    target: __ENV.RAMP_TARGET
                        ? parseInt(__ENV.RAMP_TARGET, 10)
                        : 50,
                },
                { duration: "1m", target: 0 },
            ],
            gracefulStop: "30s",
            startTime: "30s",
        },
    },
    thresholds: {
        http_req_failed: ["rate<0.02"], // < 2% failures
        http_req_duration: ["p(90)<800", "p(99)<1500"], // latency SLO
        "cart_add_item_duration{op:add}": ["p(90)<800"],
        "cart_fetch_duration{op:get}": ["p(90)<600"],
    },
    summaryTrendStats: ["avg", "min", "med", "max", "p(90)", "p(95)", "p(99)"],
};

// ---------------- Metrics ----------------
const addItemTrend = new Trend("cart_add_item_duration", true);
const fetchTrend = new Trend("cart_fetch_duration", true);
const checkoutTrend = new Trend("cart_checkout_duration", true);
const addedItemsCounter = new Counter("cart_items_added");
const checkoutCounter = new Counter("cart_checkout_calls");

// ---------------- SKUs ----------------
const SKUS = [
    "778290",
    "778345",
    "778317",
    "778277",
    "778267",
    "778376",
    "778244",
    "778384",
    "778365",
    "778377",
    "778255",
    "778286",
    "778246",
    "778270",
    "778266",
    "778285",
    "778329",
    "778425",
    "778407",
    "778418",
    "778430",
    "778469",
    "778358",
    "778351",
    "778319",
    "778307",
    "778278",
    "778251",
    "778253",
    "778261",
    "778263",
    "778273",
    "778281",
    "778294",
    "778297",
    "778302",
];

// ---------------- Helpers ----------------
function randomSku() {
    return SKUS[Math.floor(Math.random() * SKUS.length)];
}
function randomQty() {
    return 1 + Math.floor(Math.random() * 3); // 1..3
}
function baseUrl() {
    const u = __ENV.BASE_URL || "http://localhost:8080/cart";
    // Allow user to pass either root host or full /cart path
    return u.endsWith("/cart") ? u : u.replace(/\/+$/, "") + "/cart";
}
function extractCookie(res, name) {
    const cookies = res.cookies[name];
    if (!cookies || cookies.length === 0) return null;
    return cookies[0].value;
}
function withCookies(headers, cookieJar) {
    if (!cookieJar || Object.keys(cookieJar).length === 0) return headers;
    const cookieStr = Object.entries(cookieJar)
        .map(([k, v]) => `${k}=${v}`)
        .join("; ");
    return { ...headers, Cookie: cookieStr };
}

// Maintain cart + owner cookies per VU
let cartState = {
    cartid: null,
    cartowner: null,
};

// Refresh cookies from response
function updateCookies(res) {
    const cid = extractCookie(res, "cartid");
    if (cid) cartState.cartid = cid;
    const owner = extractCookie(res, "cartowner");
    if (owner) cartState.cartowner = owner;
}

// Build headers
function headers() {
    const h = { "Content-Type": "application/json" };
    const jar = {};
    if (cartState.cartid) jar["cartid"] = cartState.cartid;
    if (cartState.cartowner) jar["cartowner"] = cartState.cartowner;
    return withCookies(h, jar);
}

// Ensure cart exists (GET /)
function ensureCart() {
    if (cartState.cartid) return;
    const res = http.get(baseUrl() + "/", { headers: headers() });
    updateCookies(res);
    check(res, {
        "ensure cart status 200": (r) => r.status === 200,
        "ensure cart has id": () => !!cartState.cartid,
    });
}

// Add random item
function addRandomItem() {
    const payload = JSON.stringify({
        sku: randomSku(),
        quantity: randomQty(),
        country: "no",
    });
    const start = Date.now();
    const res = http.post(baseUrl(), payload, { headers: headers() });
    const dur = Date.now() - start;
    addItemTrend.add(dur, { op: "add" });
    if (res.status === 200) {
        addedItemsCounter.add(1);
    }
    updateCookies(res);
    check(res, {
        "add item status ok": (r) => r.status === 200,
    });
}

// Fetch cart state
function fetchCart() {
    const start = Date.now();
    const res = http.get(baseUrl() + "/", { headers: headers() });
    const dur = Date.now() - start;
    fetchTrend.add(dur, { op: "get" });
    updateCookies(res);
    check(res, { "fetch status ok": (r) => r.status === 200 });
}

// Occasional checkout trigger
function maybeCheckout() {
    if (!cartState.cartid) return;
    // // Small probability
    // if (Math.random() < 0.02) {
    //     const start = Date.now();
    //     const res = http.get(baseUrl() + "/checkout", { headers: headers() });
    //     const dur = Date.now() - start;
    //     checkoutTrend.add(dur, { op: "checkout" });
    //     updateCookies(res);
    //     if (res.status === 200) checkoutCounter.add(1);
    //     check(res, { "checkout status ok": (r) => r.status === 200 });
    // }
}

// ---------------- k6 lifecycle ----------------
export function setup() {
    // Provide SKU list length for summary
    return { skuCount: SKUS.length };
}

export default function (data) {
    group("cart flow", () => {
        // Create or reuse cart
        ensureCart();

        // Random number of item mutations per iteration (1..5)
        const ops = 1 + Math.floor(Math.random() * 5);
        for (let i = 0; i < ops; i++) {
            addRandomItem();
        }

        // Fetch state
        fetchCart();

        // Optional checkout attempt
        maybeCheckout();
    });

    // Small think time
    sleep(Math.random() * 0.5);
}

export function teardown(data) {
    // Optionally we could GET confirmation or clear cart cookie
    // Not implemented for load purpose.
    console.log(`Test complete. SKU count: ${data.skuCount}`);
}

// ---------------- Summary ----------------
export function handleSummary(data) {
    return {
        stdout: JSON.stringify(
            {
                metrics: {
                    mutations_avg: data.metrics.cart_add_item_duration?.avg,
                    mutations_p95: data.metrics.cart_add_item_duration?.p(95),
                    fetch_p95: data.metrics.cart_fetch_duration?.p(95),
                    checkout_count: data.metrics.cart_checkout_calls?.count,
                },
                checks: data.root_checks,
            },
            null,
            2,
        ),
    };
}
