"""``/api/v1`` Blueprint及其局部HTTP基础设施。"""

from __future__ import annotations

import logging

from flask import Blueprint, Flask, request
from werkzeug.exceptions import RequestEntityTooLarge

from dms.common.errors import DmsError
from dms.common.request_context import REQUEST_ID_HEADER, get_request_id, initialize_request_id
from dms.common.response import error_response

logger = logging.getLogger(__name__)

api_v1 = Blueprint("dms_api_v1", __name__, url_prefix="/api/v1")
EXPOSED_RESPONSE_HEADERS = ("Content-Disposition", "X-Request-Id")


@api_v1.before_request
def _before_dms_request() -> None:
    initialize_request_id()


@api_v1.after_request
def _after_dms_request(response):
    response.headers[REQUEST_ID_HEADER] = get_request_id()
    return response


@api_v1.errorhandler(DmsError)
def _handle_dms_error(error: DmsError):
    return error_response(
        error.code,
        error.message,
        details=error.details,
        status=error.status_code,
    )


@api_v1.errorhandler(RequestEntityTooLarge)
def _handle_request_too_large(_error: RequestEntityTooLarge):
    return error_response(
        "PAYLOAD_TOO_LARGE",
        "请求内容过大",
        details=None,
        status=413,
    )


@api_v1.errorhandler(Exception)
def _handle_unexpected_error(error: Exception):
    logger.exception("未处理的DMS接口异常", exc_info=error)
    return error_response(
        "INTERNAL_ERROR",
        "服务器内部错误",
        details=None,
        status=500,
    )


def register_dms_routing_error_handlers(app: Flask) -> None:
    """让未匹配到Blueprint的 ``/api/v1`` 404也使用DMS错误结构。

    其他路径直接返回Werkzeug原始异常，保持既有 ``/api/*`` 行为。
    """

    @app.errorhandler(404)
    def _handle_routing_not_found(error):
        if request.path == "/api/v1" or request.path.startswith("/api/v1/"):
            try:
                initialize_request_id()
            except DmsError as request_id_error:
                return _handle_dms_error(request_id_error)
            return error_response(
                "RESOURCE_NOT_FOUND",
                "请求的资源不存在",
                details=None,
                status=404,
            )
        return error


def _merge_exposed_headers(existing: str | None) -> str:
    """大小写无关地合并浏览器可读响应头，并保持已有声明。"""
    values: list[str] = []
    seen: set[str] = set()
    for value in (existing or "").split(","):
        normalized = value.strip()
        key = normalized.lower()
        if normalized and key not in seen:
            values.append(normalized)
            seen.add(key)
    for value in EXPOSED_RESPONSE_HEADERS:
        key = value.lower()
        if key not in seen:
            values.append(value)
            seen.add(key)
    return ", ".join(values)


def register_dms_response_headers(app: Flask) -> None:
    """仅为DMS路径补充跨域可读响应头，覆盖路由级错误。"""

    @app.after_request
    def _expose_dms_response_headers(response):
        if request.path == "/api/v1" or request.path.startswith("/api/v1/"):
            response.headers["Access-Control-Expose-Headers"] = (
                _merge_exposed_headers(
                    response.headers.get("Access-Control-Expose-Headers")
                )
            )
        return response


from dms.api.v1 import health  # noqa: E402,F401
from dms.api.v1 import (  # noqa: E402,F401
    audit,
    auth,
    categories,
    documents,
    organizations,
    recycle_bin,
    runtime_config,
    ui_dictionaries,
    users,
)
