import sys, os, asyncio, traceback
from io import BytesIO

CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, CURRENT_DIR)

from dotenv import load_dotenv
load_dotenv(os.path.join(CURRENT_DIR, ".env"))

_loop = asyncio.new_event_loop()
asyncio.set_event_loop(_loop)

try:
    import server as server_module
    fastapi_app = server_module.app

    def _init_motor():
        import motor.motor_asyncio
        mongo_url = os.environ.get("MONGO_URL", "")
        db_name = os.environ.get("DB_NAME", "dopebling_app")
        client = motor.motor_asyncio.AsyncIOMotorClient(mongo_url)
        db = client[db_name]
        server_module.client = client
        server_module.db = db
        server_module.app.state.db = db

    _init_motor()

    def application(environ, start_response):
        asyncio.set_event_loop(_loop)

        path = environ.get("PATH_INFO", "/")
        script_name = environ.get("SCRIPT_NAME", "")
        method = environ.get("REQUEST_METHOD", "GET")
        query = environ.get("QUERY_STRING", "")
        length = int(environ.get("CONTENT_LENGTH", 0) or 0)
        body = environ["wsgi.input"].read(length) if length else b""

        headers = []
        for k, v in environ.items():
            if k.startswith("HTTP_"):
                headers.append((k[5:].lower().replace("_", "-").encode("latin1"), v.encode("latin1")))
        if "CONTENT_TYPE" in environ:
            headers.append((b"content-type", environ["CONTENT_TYPE"].encode("latin1")))
        if length:
            headers.append((b"content-length", str(length).encode("latin1")))

        scope = {
            "type": "http",
            "asgi": {"version": "3.0"},
            "http_version": "1.1",
            "method": method,
            "path": path,
            "raw_path": path.encode("latin1"),
            "query_string": query.encode("latin1"),
            "root_path": script_name,
            "headers": headers,
        }

        resp = []
        buf = BytesIO()
        body_sent = False
        disconnect_event = asyncio.Event()

        async def recv():
            nonlocal body_sent
            if not body_sent:
                body_sent = True
                return {"type": "http.request", "body": body, "more_body": False}
            await disconnect_event.wait()
            return {"type": "http.disconnect"}

        async def send(msg):
            if msg["type"] == "http.response.start":
                resp.append((msg["status"], msg.get("headers", [])))
            elif msg["type"] == "http.response.body":
                buf.write(msg.get("body", b""))

        _loop.run_until_complete(fastapi_app(scope, recv, send))

        if not resp:
            start_response("500 Internal Server Error", [("Content-Type", "text/plain")])
            return [b"No response from ASGI app"]

        status_code, resp_headers = resp[0]
        start_response(
            f"{status_code} OK",
            [(k.decode("latin1"), v.decode("latin1")) for k, v in resp_headers]
        )
        return [buf.getvalue()]

except Exception:
    err_msg = traceback.format_exc()
    def application(environ, start_response):
        start_response("500 Internal Server Error", [("Content-Type", "text/html; charset=utf-8")])
        return [f"<h2>Python Startup Error</h2><pre>{err_msg}</pre>".encode("utf-8")]
