package shop;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * A tiny shop served by the JDK's built-in HTTP server, in two versions of the same app.
 *
 * <p>/v1 is the page the tests are written against. /v2 is the same shop after a redesign: a promo
 * banner above the header, renamed classes, a different button label, no element ids, no Search
 * button (the list filters as you type), and prices shown as "&#8377;120.00". The add-to-cart call
 * takes between 80 and 419 ms, as a real backend does, so the cart badge updates after a click, not during it.
 * Every element carries a data-testid in both versions: that is the stable contract the repaired tests use.
 */
public final class ShopServer implements AutoCloseable {

    private final HttpServer server;
    private final AtomicInteger calls = new AtomicInteger();

    public ShopServer() throws IOException {
        server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
        server.createContext("/", this::handle);
        server.start();
    }

    public String url(String version) {
        return "http://127.0.0.1:" + server.getAddress().getPort() + "/" + version;
    }

    private void handle(HttpExchange ex) throws IOException {
        String path = ex.getRequestURI().getPath();
        byte[] body;
        String type = "text/html; charset=utf-8";
        if (path.equals("/v1") || path.equals("/v2")) {
            body = page(path.equals("/v1")).getBytes(StandardCharsets.UTF_8);
        } else if (path.equals("/api/add")) {
            try {
                Thread.sleep(80 + (calls.incrementAndGet() * 137L) % 340);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            type = "application/json";
            body = "{\"ok\":true}".getBytes(StandardCharsets.UTF_8);
        } else {
            ex.sendResponseHeaders(404, -1);
            return;
        }
        ex.getResponseHeaders().add("Content-Type", type);
        ex.sendResponseHeaders(200, body.length);
        ex.getResponseBody().write(body);
        ex.close();
    }

    private static String product(boolean v1, String slug, String name, String price) {
        return v1
                ? "<div class=\"card\" data-testid=\"product-" + slug + "\"><h3>" + name + "</h3>"
                  + "<span class=\"price\" data-testid=\"price-" + slug + "\">&#8377;" + price + "</span>"
                  + "<button class=\"btn btn-primary\" data-testid=\"add-" + slug + "\">Add to cart</button></div>"
                : "<article class=\"product-tile\" data-testid=\"product-" + slug + "\"><h3>" + name + "</h3>"
                  + "<span class=\"amount\" data-testid=\"price-" + slug + "\">&#8377;" + price + ".00</span>"
                  + "<button class=\"btn-add\" data-testid=\"add-" + slug + "\">Add</button></article>";
    }

    private static String page(boolean v1) {
        String items = product(v1, "notebook", "Notebook", "120") + product(v1, "pen", "Pen", "30")
                + product(v1, "bag", "Bag", "899");
        String header = v1
                ? "<header><input id=\"q\" data-testid=\"search\" placeholder=\"Search products\">"
                  + "<button class=\"btn btn-primary\" id=\"go\">Search</button>"
                  + "<span>Cart: <b id=\"cart-count\" data-testid=\"cart-count\">0</b></span></header>"
                  + "<div class=\"grid\">" + items + "</div>"
                : "<div class=\"promo\">Diwali sale: free shipping</div>"
                  + "<header><input name=\"q\" data-testid=\"search\" placeholder=\"Search products\">"
                  + "<span class=\"pill\" data-testid=\"cart-count\">0</span></header>"
                  + "<section class=\"tiles\">" + items + "</section>";
        String tile = v1 ? ".card" : ".product-tile";
        String add = v1 ? ".btn-primary" : ".btn-add";
        return "<!doctype html><html><head><meta charset=\"utf-8\"><title>Shop " + (v1 ? "v1" : "v2") + "</title></head><body>"
                + header + "<script>"
                + "let cart=0;"
                + "const badge=document.querySelector('[data-testid=cart-count]');"
                + "document.querySelectorAll('" + tile + " " + add + "').forEach(b=>b.addEventListener('click',()=>{"
                + "fetch('/api/add').then(()=>{cart++;badge.textContent=cart;});}));"
                + "const q=document.querySelector('[data-testid=search]');"
                + "function filter(){const t=q.value.toLowerCase();document.querySelectorAll('" + tile + "').forEach(c=>{"
                + "c.style.display=c.querySelector('h3').textContent.toLowerCase().includes(t)?'':'none';});}"
                + "q.addEventListener('input',filter);"
                + (v1 ? "document.getElementById('go').addEventListener('click',filter);" : "")
                + "</script></body></html>";
    }

    @Override
    public void close() {
        server.stop(0);
    }
}
