from __future__ import annotations

import json
import threading
from http.client import HTTPConnection
from http.server import ThreadingHTTPServer

from kernite.cli import _GovernanceHandler


def _start_server() -> tuple[ThreadingHTTPServer, threading.Thread]:
    server = ThreadingHTTPServer(("127.0.0.1", 0), _GovernanceHandler)
    thread = threading.Thread(target=server.serve_forever, daemon=True)
    thread.start()
    return server, thread


def _post_json(path: str, payload: object) -> tuple[int, dict]:
    server, thread = _start_server()
    try:
        host, port = server.server_address
        conn = HTTPConnection(host, port, timeout=5)
        body = json.dumps(payload).encode("utf-8")
        conn.request(
            "POST",
            path,
            body=body,
            headers={"Content-Type": "application/json"},
        )
        response = conn.getresponse()
        status = response.status
        data = json.loads(response.read().decode("utf-8"))
        conn.close()
        return status, data
    finally:
        server.shutdown()
        server.server_close()
        thread.join(timeout=2)


def test_validate_endpoint_reports_non_object_body_as_validation_error():
    status, data = _post_json("/validate/execute", ["not", "an", "object"])

    assert status == 200
    assert data["data"]["valid"] is False
    assert any(error["field"] == "body" for error in data["data"]["errors"])


def test_execute_endpoint_keeps_non_object_body_as_http_400():
    status, data = _post_json("/execute", ["not", "an", "object"])

    assert status == 400
    assert data["message"] == "Request body must be an object"
