package com.mosquito.project.sdk;

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.Map;
import java.util.concurrent.ConcurrentHashMap;

class TestHttpServer implements AutoCloseable {

    private static final class Response {
        private final int status;
        private final String contentType;
        private final byte[] body;

        private Response(int status, String contentType, byte[] body) {
            this.status = status;
            this.contentType = contentType;
            this.body = body;
        }
    }

    private final HttpServer server;
    private final Map<String, Response> responses = new ConcurrentHashMap<>();

    TestHttpServer() {
        try {
            this.server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
        } catch (IOException e) {
            throw new RuntimeException("Failed to start test server", e);
        }
        this.server.createContext("/", this::handle);
        this.server.start();
    }

    String baseUrl() {
        return "http://localhost:" + server.getAddress().getPort();
    }

    void register(String method, String path, int status, String contentType, byte[] body) {
        responses.put(key(method, path), new Response(status, contentType, body));
    }

    void registerJson(String method, String path, String json) {
        register(method, path, 200, "application/json", json.getBytes(StandardCharsets.UTF_8));
    }

    void registerText(String method, String path, String text) {
        register(method, path, 200, "text/plain", text.getBytes(StandardCharsets.UTF_8));
    }

    private void handle(HttpExchange exchange) throws IOException {
        String requestKey = key(exchange.getRequestMethod(), exchange.getRequestURI().getPath());
        Response response = responses.get(requestKey);
        if (response == null) {
            exchange.sendResponseHeaders(404, -1);
            exchange.close();
            return;
        }
        if (response.contentType != null) {
            exchange.getResponseHeaders().add("Content-Type", response.contentType);
        }
        if (response.body == null) {
            exchange.sendResponseHeaders(response.status, -1);
            exchange.close();
            return;
        }
        exchange.sendResponseHeaders(response.status, response.body.length);
        exchange.getResponseBody().write(response.body);
        exchange.close();
    }

    private String key(String method, String path) {
        return method + " " + path;
    }

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