try:
    from lchttp.json import json_dumps
except ImportError:
    from json import dumps as json_dumps
import logging
import threading
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler
from socketserver import TCPServer
from typing import Any, Callable, Type
from urllib.parse import unquote

_logger = logging.getLogger(__name__)


class _ReuseAddressTcpServer(TCPServer):
    def __init__(self, host: str, port: int, handler_class: Type[BaseHTTPRequestHandler]) -> None:
        self.allow_reuse_address = True
        TCPServer.__init__(self, (host, port), handler_class)


def read_request_parameters(path: str) -> dict[str, Any]:
    params_received = {}
    idx = path.find('?')
    if idx >= 0 and (idx < len(path) - 1):
        for params in path[idx + 1 :].split('&'):
            param_splitted = params.split('=')
            if len(param_splitted) == 2:
                params_received[param_splitted[0]] = unquote(param_splitted[1])
    return params_received


def start_http_server(
    port: int,
    host: str = '',
    callback: Callable[[dict[Any, Any]], None] | None = None,
) -> TCPServer:
    class Handler(BaseHTTPRequestHandler):
        def do_GET(self) -> None:
            _logger.debug('GET - %s', self.path)
            params_received = read_request_parameters(self.path)
            response = (
                'Response received (%s). Result was transmitted to the original thread. '
                'You can close this window.' % json_dumps(params_received)
            )
            self.send_response(HTTPStatus.OK, 'OK')
            self.send_header("Content-type", 'text/plain')
            self.send_header("Content-Length", str(len(response)))
            self.end_headers()
            try:
                self.wfile.write(bytes(response, 'UTF-8'))
            finally:
                if callback is not None:
                    callback(params_received)
                self.wfile.flush()

    _logger.debug('start_http_server - instantiating server to listen on "%s:%d"', host, port)
    httpd = _ReuseAddressTcpServer(host, port, Handler)

    def serve() -> None:
        _logger.debug('server daemon - starting server')
        httpd.serve_forever()
        _logger.debug('server daemon - server stopped')

    thread_type = threading.Thread(target=serve)
    thread_type.start()
    return httpd


def stop_http_server(httpd: TCPServer) -> None:
    _logger.debug('stop_http_server - stopping server')
    httpd.shutdown()


__all__ = (
    'read_request_parameters',
    'start_http_server',
    'stop_http_server',
)
