"""API method bridge that converts GET requests to POST/DELETE.

Allows triggering POST/DELETE API calls from browser links without JavaScript.
"""

from urllib.parse import urlencode

from fastapi import APIRouter
from mm_http import http_request
from starlette.requests import Request
from starlette.responses import PlainTextResponse

from mm_base6.config import Config
from mm_base6.server.cbv import cbv
from mm_base6.server.deps import InternalView
from mm_base6.server.middleware.auth import ACCESS_TOKEN_NAME

router: APIRouter = APIRouter(include_in_schema=False)
"""Router for API method bridge endpoints (not included in OpenAPI schema)."""


@cbv(router)
class ApiMethodRouter(InternalView):
    """Routes that proxy GET requests to POST/DELETE API calls."""

    @router.get("/api-post/{url:path}")
    async def api_post(self, url: str, request: Request) -> object:
        """Proxy a GET request to POST /api/{url}."""
        return await _api_method("post", url, self.config, request)

    @router.get("/api-delete/{url:path}")
    async def api_delete(self, url: str, request: Request) -> object:
        """Proxy a GET request to DELETE /api/{url}."""
        return await _api_method("delete", url, self.config, request)


async def _api_method(method: str, url: str, config: Config, req: Request) -> object:
    """Execute an internal API request with the given HTTP method."""
    base_url = str(req.base_url)
    if not base_url.endswith("/"):
        base_url = base_url + "/"
    url = base_url + "api/" + url
    # TODO: Replace use_https with base_url config or X-Forwarded-Proto header support
    if config.use_https:
        url = url.replace("http://", "https://", 1)
    if req.query_params:
        url += "?" + urlencode(dict(req.query_params))

    headers = {ACCESS_TOKEN_NAME: config.access_token}
    res = await http_request(url, method=method, headers=headers, json=dict(req.query_params), timeout=600)

    if res.content_type and res.content_type.startswith("text/plain"):
        return PlainTextResponse(res.body)
    json_res = res.json_body_or_none()
    if json_res is not None:
        return json_res
    return res.body
