"""Runtime API gateway for tenant-aware SaaS request handling."""

from __future__ import annotations

import importlib
import importlib.util

from flask import Request, jsonify

from platform.logging.platform_logger import get_platform_logger, log_structured
from platform.routing.request_context import build_request_context
from platform.routing.tenant_resolver import resolve_tenant


class APIGateway:
    """Resolve tenant context and dispatch requests into app handlers."""

    def __init__(self) -> None:
        self.logger = get_platform_logger("api_gateway")

    def handle(self, flask_request: Request, app_name: str, action: str):
        """Handle one incoming request through the SaaS runtime flow."""
        try:
            tenant_data = resolve_tenant(flask_request)
            context = build_request_context(flask_request, tenant_data)
        except ValueError as exc:
            return jsonify({"status": "error", "message": str(exc)}), 400
        except LookupError as exc:
            return jsonify({"status": "error", "message": str(exc)}), 404
        except PermissionError as exc:
            return jsonify({"status": "error", "message": str(exc)}), 403
        except Exception as exc:
            return jsonify({"status": "error", "message": f"Gateway failure: {exc}"}), 500

        if context["app_id"] and context["app_id"] != app_name:
            return jsonify(
                {
                    "status": "error",
                    "message": f"X-App-ID mismatch: header={context['app_id']} path={app_name}",
                }
            ), 400

        log_structured(
            self.logger,
            "gateway_request",
            request_id=context["request_id"],
            tenant_id=context["tenant"]["tenant_id"],
            app_id=context["app_id"],
            action=action,
            method=flask_request.method,
            path=flask_request.path,
            user_id=context.get("user_id"),
            remote_addr=flask_request.remote_addr,
        )
        return self.route_to_app(context, app_name, action)

    def route_to_app(self, context: dict[str, object], app_name: str, action: str):
        if importlib.util.find_spec(f"apps.{app_name}") is None:
            return jsonify({"status": "error", "message": f"Unknown app: {app_name}"}), 404

        try:
            module = importlib.import_module(f"apps.{app_name}")
        except Exception as exc:
            return jsonify({"status": "error", "message": f"Failed to load app {app_name}: {exc}"}), 500

        handler = getattr(module, "handle_request", None)
        if handler is None:
            return jsonify({"status": "error", "message": f"App does not expose handle_request: {app_name}"}), 404

        try:
            result = handler(context, action)
        except Exception as exc:
            log_structured(
                self.logger,
                "gateway_app_error",
                request_id=context.get("request_id"),
                tenant_id=(context.get("tenant") or {}).get("tenant_id") if isinstance(context.get("tenant"), dict) else None,
                app_id=app_name,
                action=action,
                message=str(exc),
            )
            return jsonify({"status": "error", "message": str(exc)}), 500

        if isinstance(result, tuple):
            payload, status_code = result
            if isinstance(payload, dict):
                return jsonify(payload), status_code
            return payload, status_code
        if isinstance(result, dict):
            return jsonify(result)
        return result
