import os
import sys
import asyncio
from http import HTTPStatus

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

from app.main import app as asgi_app
from app.models.database import create_tables

create_tables()


def _asgi_to_wsgi(app):
    def application(environ, start_response):
        headers = []
        for key, value in environ.items():
            if key.startswith("HTTP_"):
                name = key[5:].replace("_", "-").lower().encode("latin-1")
                headers.append((name, str(value).encode("latin-1")))
            elif key in ("CONTENT_TYPE", "CONTENT_LENGTH") and value:
                name = key.replace("_", "-").lower().encode("latin-1")
                headers.append((name, str(value).encode("latin-1")))

        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""

        path = environ.get("PATH_INFO", "") or "/"
        scope = {
            "type": "http",
            "asgi": {"version": "3.0", "spec_version": "2.3"},
            "http_version": environ.get("SERVER_PROTOCOL", "HTTP/1.1").split("/")[-1],
            "method": environ["REQUEST_METHOD"],
            "scheme": environ.get("wsgi.url_scheme", "http"),
            "path": path,
            "raw_path": path.encode("latin-1", errors="ignore"),
            "query_string": (environ.get("QUERY_STRING") or "").encode("latin-1"),
            "headers": headers,
            "server": (environ.get("SERVER_NAME", "localhost"), int(environ.get("SERVER_PORT", "80"))),
            "client": (environ.get("REMOTE_ADDR", "127.0.0.1"), int(environ.get("REMOTE_PORT", "0") or 0)),
            "root_path": environ.get("SCRIPT_NAME", ""),
        }

        response_status = 500
        response_headers = [(b"content-type", b"text/plain; charset=utf-8")]
        response_chunks = []
        request_sent = False

        async def receive():
            nonlocal request_sent
            if request_sent:
                return {"type": "http.disconnect"}
            request_sent = True
            return {"type": "http.request", "body": body, "more_body": False}

        async def send(message):
            nonlocal response_status, response_headers
            msg_type = message.get("type")
            if msg_type == "http.response.start":
                response_status = int(message.get("status", 200))
                response_headers = message.get("headers", [])
            elif msg_type == "http.response.body":
                response_chunks.append(message.get("body", b""))

        try:
            asyncio.run(app(scope, receive, send))
        except Exception:
            import traceback
            response_status = 500
            response_headers = [(b"content-type", b"text/plain; charset=utf-8")]
            response_chunks = [traceback.format_exc().encode("utf-8", errors="ignore")]

        reason = HTTPStatus(response_status).phrase if response_status in HTTPStatus._value2member_map_ else ""
        status_line = f"{response_status} {reason}".strip()
        headers_out = [
            (name.decode("latin-1"), value.decode("latin-1"))
            for name, value in response_headers
        ]
        start_response(status_line, headers_out)
        return [b"".join(response_chunks)]

    return application


application = _asgi_to_wsgi(asgi_app)
