import inspect
import sys
from typing import Optional

from algo_backend.config import ErrorCodeConfig

from . import status_code
from .status_code import BasicApiId, BasicApiInnerErrorCode, BasicStatusCode


class ApiErrorCodeManage:
    """
    构建”5aaabb“错误码，aaa接口id，bb表示接口内部错误码
    """

    @classmethod
    def set_error_code_prefix_env(cls, prefix: Optional[int] = None):
        """
        服务启动时执行这个函数
        也可以启动服务时通过环境变量ERROR_CODE_SERVICE_PREFIX指定服务前缀
        如果输入的prefix code不符合规则，则忽略，保持原来的6位
        """
        if prefix and 1 <= prefix <= 99:
            ErrorCodeConfig.SERVICE_PREFIX = prefix

    @classmethod
    def scan_module_and_summary(cls, *list_module) -> list:
        """扫描模块中的ApiId和错误码枚举类"""
        api_id_dict: dict = {}
        api_err_code_info = []

        cls_list = []
        for m in list_module:
            cls_list.extend(
                [obj for name, obj in inspect.getmembers(m) if inspect.isclass(obj)]
            )

        for obj in set(cls_list):
            # 查找继承自BasicApiId的枚举类
            if issubclass(obj, BasicApiId) and obj != BasicApiId:
                for enum_member in obj:
                    api_id_dict[enum_member.value] = enum_member.name
                    api_err_code_info.append(
                        [
                            enum_member.value,
                            BasicApiInnerErrorCode.gen_standard_code(enum_member, 0),
                            "",
                        ]
                    )

            # 查找继承自BasicApiInnerErrorCode的枚举类
            elif (
                issubclass(obj, BasicApiInnerErrorCode)
                and obj != BasicApiInnerErrorCode
                and hasattr(obj, "__api_id__")
            ):
                api_id_enum: BasicApiId = getattr(obj, "__api_id__")
                for enum_member in obj:
                    api_err_code_info.append(
                        [
                            api_id_enum.value,
                            BasicApiInnerErrorCode.gen_standard_code(
                                api_id_enum, enum_member.value
                            ),
                            enum_member.msg,
                        ]
                    )

        for idx, (api_code, _, _) in enumerate(api_err_code_info):
            api_err_code_info[idx][0] = api_id_dict[api_code]

        # 排序
        api_err_code_info.sort(key=lambda x: x[1])

        return api_err_code_info

    @classmethod
    def summary_module_api_error_code_markdown(cls, *list_module):
        """
        打印模块中的ApiId和错误码枚举类
        """
        result = cls.scan_module_and_summary(*list_module)

        print("| ApiName | ErrorCode | Message |")
        print("|--------|------------|---------|")
        for api_id, api_code, msg in result:
            print(f"| {api_id} | {api_code} | {msg} |")


class BasicCodeManage:
    __DEFAULT_MODULE = sys.modules[status_code.__name__]

    @classmethod
    def scan_module_and_summary(cls, *list_module) -> list:
        """扫描模块中BasicStatusCode枚举类及其子类"""
        if cls.__DEFAULT_MODULE not in list_module:
            list_module = list_module + (cls.__DEFAULT_MODULE,)

        result = []
        cls_list = []

        for m in list_module:
            cls_list.extend(
                [obj for name, obj in inspect.getmembers(m) if inspect.isclass(obj)]
            )

        for obj in set(cls_list):
            if issubclass(obj, BasicStatusCode) and obj != BasicApiId:
                for enum_member in obj:
                    result.append([enum_member.value, enum_member.msg])

        result.sort(key=lambda x: x[0])

        return result

    @classmethod
    def summary_error_code_markdown(cls, *list_module):
        """
        打印模块中的ApiId和错误码枚举类
        """
        result = cls.scan_module_and_summary(*list_module)

        print("| Code | Message |")
        print("|--------|------------|")
        for code, msg in result:
            print(f"| {code} | {msg} |")
