"""
passenger_wsgi.py — FastAPI + PostgreSQL (JSONB) via pg_adapter
===============================================================
Replaces Motor/MongoDB with pg_adapter over PostgreSQL.
The FastAPI app (server.py) runs unchanged.
"""
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)

PG_DSN = os.environ.get(
    "PG_DSN",
    "host=127.0.0.1 port=5432 dbname=dopebling_app user=dopebling_idgapp password=Romania95!"
)

try:
    import server as server_module
    fastapi_app = server_module.app

    async def _init_postgres():
        from pg_adapter import init_pg
        db = await init_pg(PG_DSN)
        server_module.db = db
        server_module.app.state.db = db
        # Patch client reference so server.py doesn't crash
        class _FakeClient:
            pass
        server_module.client = _FakeClient()
        print("[passenger_wsgi] PostgreSQL initialized via pg_adapter", flush=True)

    _loop.run_until_complete(_init_postgres())

    # ── WSGI adapter (ASGI → WSGI) ──────────────────────────────────────────
    def _build_scope(environ):
        headers = []
        for key, value in environ.items():
            if key.startswith("HTTP_"):
                name = key[5:].lower().replace("_", "-").encode("latin1")
                headers.append((name, value.encode("latin1")))
        for k in ("CONTENT_TYPE", "CONTENT_LENGTH"):
            if environ.get(k):
                headers.append((k.lower().replace("_", "-").encode("latin1"),
                                 environ[k].encode("latin1")))

        server_name = environ.get("SERVER_NAME", "localhost")
        server_port = int(environ.get("SERVER_PORT", 80))

        import urllib.parse
        path_only = urllib.parse.unquote(environ.get("PATH_INFO", "/"))
        if not path_only.startswith("/api"):
            path_only = "/api" + (path_only if path_only != "/" else "")
        query = environ.get("QUERY_STRING", "")

        return {
            "type": "http",
            "asgi": {"version": "3.0"},
            "http_version": environ.get("SERVER_PROTOCOL", "HTTP/1.1").split("/")[-1],
            "method": environ["REQUEST_METHOD"].upper(),
            "headers": headers,
            "path": path_only,
            "query_string": query.encode("latin1"),
            "root_path": "",

            "scheme": environ.get("wsgi.url_scheme", "http"),
            "server": (server_name, server_port),
        }

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

        content_length = environ.get("CONTENT_LENGTH", "")
        content_length = int(content_length) if content_length.strip() else 0
        body = environ["wsgi.input"].read(content_length) if content_length > 0 else b""

        response_started = []
        response_body = []

        _body_sent = False
        async def receive():
            nonlocal _body_sent
            if not _body_sent:
                _body_sent = True
                return {"type": "http.request", "body": body, "more_body": False}
            await asyncio.sleep(86400)
            return {"type": "http.disconnect"}

        async def send(message):
            if message["type"] == "http.response.start":
                response_started.append(message)
            elif message["type"] == "http.response.body":
                response_body.append(message.get("body", b""))

        try:
            _loop.run_until_complete(fastapi_app(scope, receive, send))
        except Exception:
            tb = traceback.format_exc()
            start_response("500 Internal Server Error",
                           [("Content-Type", "application/json")])
            return [f'{{"detail": "Server error", "trace": {repr(tb)}}}'.encode()]

        if not response_started:
            start_response("500 Internal Server Error",
                           [("Content-Type", "application/json")])
            return [b'{"detail": "No response from app"}']

        rs = response_started[0]
        status_code = rs["status"]
        status_text = {
            200: "OK", 201: "Created", 204: "No Content",
            400: "Bad Request", 401: "Unauthorized", 403: "Forbidden",
            404: "Not Found", 409: "Conflict", 422: "Unprocessable Entity",
            500: "Internal Server Error",
        }.get(status_code, "Unknown")

        headers_out = []
        for name, val in rs.get("headers", []):
            n = name.decode("latin1") if isinstance(name, bytes) else name
            v = val.decode("latin1") if isinstance(val, bytes) else val
            headers_out.append((n, v))

        # Add CORS headers
        origin = environ.get("HTTP_ORIGIN", "*")
        headers_out += [
            ("Access-Control-Allow-Origin", origin),
            ("Access-Control-Allow-Credentials", "true"),
            ("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,OPTIONS"),
            ("Access-Control-Allow-Headers", "Authorization,Content-Type,X-Requested-With"),
        ]

        # Handle OPTIONS preflight
        if environ["REQUEST_METHOD"].upper() == "OPTIONS":
            start_response("204 No Content", headers_out)
            return [b""]

        start_response(f"{status_code} {status_text}", headers_out)
        return response_body if response_body else [b""]

except Exception as e:
    tb = traceback.format_exc()
    _err_msg = str(e)
    print(f"[passenger_wsgi] STARTUP ERROR: {_err_msg}\n{tb}", flush=True)

    def application(environ, start_response):
        start_response("503 Service Unavailable", [("Content-Type", "application/json")])
        return [f'{{"detail": "Startup failed: {_err_msg}"}}'.encode()]
