from abc import ABC, abstractmethod
from typing import Dict, Optional

from starlette.requests import Request

from algo_backend.schema import AbstractRespVo, BaseRespVo
from algo_backend.utils.utils import gen_random_request_id


class BasicExceptionInterceptor(ABC):
    """
    拦截接口关于schema检验的报错，并返回约定的body
    """

    def __init__(
        self,
        default_vo_type: type(AbstractRespVo) = BaseRespVo,
        url_vo_dict: Optional[Dict[str, type(AbstractRespVo)]] = None,
    ):
        self.default_vo_type: type(AbstractRespVo) = default_vo_type
        # url和响应的匹配策略
        self.url_vo_dict = url_vo_dict or {}

    def get_vo_type(self, url: str) -> type(AbstractRespVo):
        """
        用户可以继承BasicExceptionInterceptor的子类，覆盖这个方法从而实现更加复杂的url和响应体匹配策略
        :param url:
        :return:
        """
        return self.url_vo_dict.get(url, self.default_vo_type)

    @classmethod
    def extract_url(cls, request: Request):
        try:
            url = request.url.path
        except Exception:
            url = ""
        return url

    @classmethod
    def get_request_id(cls, request: Request):
        return request.headers.get("x-request-id", gen_random_request_id())

    @abstractmethod
    def intercept(self, request: Request, exc: Exception): ...
