"""WSGI adapter for deploying MailPulse on cPanel / Phusion Passenger (Benzahosting)."""

import io
import os
import sys

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
if BASE_DIR not in sys.path:
    sys.path.insert(0, BASE_DIR)

from server import AppContext, make_handler_class

_app_ctx = None
_handler_cls = None


def _get_handler():
    global _app_ctx, _handler_cls
    if _handler_cls is None:
        db_path = os.environ.get("MAILPULSE_DB_PATH") or os.path.join(BASE_DIR, "mailpulse.db")
        _app_ctx = AppContext(db_path=db_path, require_auth=True)
        _handler_cls = make_handler_class(_app_ctx)
    return _handler_cls


class _WSGISocket:
    """In-memory socket bridge for BaseHTTPRequestHandler."""

    def __init__(self, raw_request: bytes):
        self._rfile = io.BytesIO(raw_request)
        self._wfile = io.BytesIO()

    def makefile(self, mode, *args, **kwargs):
        return self._rfile if "r" in mode else self._wfile

    def sendall(self, data):
        self._wfile.write(data)

    def close(self):
        pass


def application(environ, start_response):
    """PEP 3333 WSGI entrypoint."""
    method = environ.get("REQUEST_METHOD", "GET").upper()
    path = environ.get("PATH_INFO", "/") or "/"
    query = environ.get("QUERY_STRING", "")
    target = f"{path}?{query}" if query else path

    try:
        content_length = int(environ.get("CONTENT_LENGTH") or 0)
    except ValueError:
        content_length = 0
    body = environ["wsgi.input"].read(content_length) if content_length > 0 else b""

    headers = []
    if environ.get("CONTENT_TYPE"):
        headers.append(("Content-Type", environ["CONTENT_TYPE"]))
    if content_length > 0:
        headers.append(("Content-Length", str(content_length)))

    scheme = environ.get("wsgi.url_scheme", "http")
    has_fwd_proto = False
    for key, val in environ.items():
        if key.startswith("HTTP_"):
            h_name = key[5:].replace("_", "-").title()
            if h_name.lower() == "x-forwarded-proto":
                has_fwd_proto = True
            headers.append((h_name, val))
    if not has_fwd_proto:
        headers.append(("X-Forwarded-Proto", scheme))

    header_block = "".join(f"{k}: {v}\r\n" for k, v in headers)
    raw_req = f"{method} {target} HTTP/1.1\r\n{header_block}\r\n".encode("utf-8") + body

    sock = _WSGISocket(raw_req)
    client_ip = environ.get("REMOTE_ADDR", "127.0.0.1")
    handler_cls = _get_handler()
    handler_cls(sock, (client_ip, 0), None)

    raw_resp = sock._wfile.getvalue()
    head, _, resp_body = raw_resp.partition(b"\r\n\r\n")
    lines = head.decode("latin-1").splitlines()
    status_line = lines[0] if lines else "HTTP/1.0 500 Internal Server Error"
    status_str = status_line.split(" ", 1)[1] if " " in status_line else "200 OK"

    resp_headers = []
    for line in lines[1:]:
        if ":" in line:
            k, v = line.split(":", 1)
            if k.strip().lower() not in ("server", "date"):
                resp_headers.append((k.strip(), v.strip()))

    start_response(status_str, resp_headers)
    return [resp_body]
