"""
施工方案审查API错误码统一定义
集中管理所有接口的错误码和错误响应格式
"""

from typing import Dict, Any
from fastapi import HTTPException
from foundation.observability.logger.loggering import review_logger as logger

class ErrorCodes:
    """错误码常量定义"""

    # 文件上传接口错误码 (WJSC001-WJSC008)
    WJSC001 = {
        "code": "WJSC001",
        "error_type": "FILE_MISSING",
        "message": "未上传文件",
        "status_code": 400
    }

    WJSC002 = {
        "code": "WJSC002",
        "error_type": "FILE_MULTIPLE",
        "message": "仅支持单文件上传",
        "status_code": 400
    }

    WJSC003 = {
        "code": "WJSC003",
        "error_type": "FILE_REJECTED",
        "message": "格式错误、内容违规、文件为空",
        "status_code": 400
    }

    WJSC004 = {
        "code": "WJSC004",
        "error_type": "FILE_FORMAT_UNSUPPORTED",
        "message": "文件格式不支持（仅允许pdf/doc/docx）",
        "status_code": 400
    }

    WJSC005 = {
        "code": "WJSC005",
        "error_type": "FILE_SIZE_EXCEEDED",
        "message": "文件过大（最大不超过50MB）",
        "status_code": 400
    }



    WJSC007 = {
        "code": "WJSC007",
        "error_type": "UNAUTHORIZED",
        "message": "认证失败（未提供或无效的Authorization）",
        "status_code": 401
    }

    WJSC008 = {
        "code": "WJSC008",
        "error_type": "INVALID_USER",
        "message": "用户标识未提供或无效",
        "status_code": 403
    }

    WJSC009 = {
        "code": "WJSC009",
        "error_type": "INVALID_PARAMETERS",
        "message": "请求参数无效或不支持",
        "status_code": 400
    }


    WJSC011 = {
        "code": "WJSC011",
        "error_type": "INTERNAL_ERROR",
        "message": "服务端内部错误",
        "status_code": 500
    }



    # 启动审查接口错误码 (QDSC001-QDSC006)
    QDSC001 = {
        "code": "QDSC001",
        "error_type": "MISSING_PARAMETERS",
        "message": "请求参数缺失",
        "status_code": 400
    }

    QDSC002 = {
        "code": "QDSC002",
        "error_type": "INVALID_PARAM_FORMAT",
        "message": "请求参数格式错误",
        "status_code": 400
    }

    QDSC003 = {
        "code": "QDSC003",
        "error_type": "UNAUTHORIZED",
        "message": "认证失败（未提供或无效的Authorization）",
        "status_code": 401
    }

    QDSC004 = {
        "code": "QDSC004",
        "error_type": "INVALID_USER",
        "message": "用户标识未提供或无效",
        "status_code": 403
    }

    QDSC005 = {
        "code": "QDSC005",
        "error_type": "TASK_NOT_FOUND",
        "message": "任务ID不存在或已过期",
        "status_code": 404
    }

    
    QDSC006 = {
        "code": "QDSC006",
        "error_type": "TASK_ALREADY_EXISTS",
        "message": "任务已存在，请勿重复提交",
        "status_code": 409
    }

    QDSC007 = {
        "code": "QDSC007",
        "error_type": "PROJECT_PLAN_TYPE_INVALID",
        "message": "无效工程方案类型（未提供或未注册）",
        "status_code": 400
    }

    QDSC008 = {
        "code": "QDSC008",
        "error_type": "ENUM_TYPE_INVALID",
        "message": "审查枚举类型无效",
        "status_code": 400
    }

    QDSC009 = {
        "code": "QDSC009",
        "error_type": "ENUM_TYPE_CANNOT_BE_NULL",
        "message": "审查枚举类型不能为空",
        "status_code": 400
    }

    QDSC010 = {
        "code": "QDSC010",
        "error_type": "FILE_INFO_NOT_FOUND",
        "message": "文件信息获取失败",
        "status_code": 500
    }

    QDSC011 = {
        "code": "QDSC011",
        "error_type": "SERVER_INTERNAL_ERROR",
        "message": "服务端内部错误",
        "status_code": 500
    }

    QDSC012 = {
        "code": "QDSC012",
        "error_type": "TASK_NOT_FOUND_OR_EXPIRED",
        "message": "任务ID不存在或已过期，请重新检查callback_task_id是否正确，或重新上传文件",
        "status_code": 404
    }

    QDSC013 = {
        "code": "QDSC013",
        "error_type": "FILE_INFO_NOT_FOUND",
        "message": "文件信息获取失败，任务ID不存在或已过期",
        "status_code": 404
    }

    QDSC014 = {
        "code": "QDSC014",
        "error_type": "TENDENCY_REVIEW_ROLE_INVALID",
        "message": "倾向性审查角色无效（未提供或未注册）",
        "status_code": 400
    }

    QDSC015 = {
        "code": "QDSC015",
        "error_type": "INVALID_REVIEW_ITEM_FORMAT",
        "message": "审查项配置格式错误，必须为「chapter_code_review_dimension」格式",
        "status_code": 400
    }

    QDSC016 = {
        "code": "QDSC016",
        "error_type": "INVALID_CHAPTER_CODE",
        "message": "章节code不支持",
        "status_code": 400
    }

    QDSC017 = {
        "code": "QDSC017",
        "error_type": "INVALID_REVIEW_DIMENSION",
        "message": "审查项code不支持",
        "status_code": 400
    }

    QDSC018 = {
        "code": "QDSC018",
        "error_type": "MUTUALLY_EXCLUSIVE_CONFIG",
        "message": "review_config与review_item_config互斥，只能提供其中一个",
        "status_code": 400
    }

    QDSC019 = {
        "code": "QDSC019",
        "error_type": "REVIEW_CONFIG_REQUIRED",
        "message": "必须提供review_config或review_item_config中的其中一个",
        "status_code": 400
    }

    QDSC020 = {
        "code": "QDSC020",
        "error_type": "DUPLICATE_REVIEW_ITEMS",
        "message": "审查项配置中存在重复项",
        "status_code": 400
    }

    QDSC021 = {
        "code": "QDSC021",
        "error_type": "CATALOGUE_COMPLETENESS_ONLY",
        "message": "目录章节仅支持完整性审查",
        "status_code": 400
    }


    # 审查结果接口错误码 (SCJG001-SCJG008)
    SCJG001 = {
        "code": "SCJG001",
        "error_type": "INVALID_TYPE",
        "message": "结果类型无效（非'summary'或'issues'）",
        "status_code": 400
    }

    SCJG002 = {
        "code": "SCJG002",
        "error_type": "MISSING_PARAM_ID",
        "message": "callback_task_id缺失",
        "status_code": 400
    }

    SCJG003 = {
        "code": "SCJG003",
        "error_type": "INVALID_ID_FORMAT",
        "message": "callback_task_id格式错误",
        "status_code": 400
    }

    SCJG004 = {
        "code": "SCJG004",
        "error_type": "UNAUTHORIZED",
        "message": "认证失败（未提供或无效的Authorization）",
        "status_code": 401
    }

    SCJG005 = {
        "code": "SCJG005",
        "error_type": "INVALID_USER",
        "message": "用户标识未提供或无效",
        "status_code": 403
    }

    SCJG006 = {
        "code": "SCJG006",
        "error_type": "TASK_NOT_FOUND",
        "message": "callback_task_id不存在或已过期",
        "status_code": 404
    }

    SCJG007 = {
        "code": "SCJG007",
        "error_type": "NO_REVIEW_RESULTS",
        "message": "无审查结果数据",
        "status_code": 404
    }

    SCJG008 = {
        "code": "SCJG008",
        "error_type": "SERVER_ERROR",
        "message": "服务端内部错误（审查结果生成失败）",
        "status_code": 500
    }


def create_http_exception(error_code: Dict[str, Any], custom_message: str = None) -> HTTPException:
    """
    创建HTTP异常

    Args:
        error_code: 错误码字典
        custom_message: 自定义错误消息，可选

    Returns:
        HTTPException: FastAPI异常对象
    """
    detail = {
        "code": error_code["code"],
        "error_type": error_code["error_type"],
        "message": custom_message or error_code["message"]
    }

    return HTTPException(
        status_code=error_code["status_code"],
        detail=detail
    )


def create_server_error(error_code: str, original_error: Exception) -> HTTPException:
    """
    创建服务器内部错误异常

    Args:
        error_code: 错误码 (如 "WJSC008", "QDSC006", "SCJG008")
        original_error: 原始异常

    Returns:
        HTTPException: FastAPI异常对象
    """
    error_map = {
        "WJSC011": ErrorCodes.WJSC011,
        "QDSC006": ErrorCodes.QDSC006,
        "SCJG008": ErrorCodes.SCJG008
    }

    error_config = error_map.get(error_code, ErrorCodes.WJSC008)
    message = f"{error_config['message']}: {str(original_error)}"

    return create_http_exception(error_config, message)


# 便捷的错误创建函数
class FileUploadErrors:
    """文件上传接口错误"""

    @staticmethod
    def file_missing():
        logger.error(ErrorCodes.WJSC001)
        return create_http_exception(ErrorCodes.WJSC001)

    @staticmethod
    def file_multiple():
        logger.error(ErrorCodes.WJSC002)
        return create_http_exception(ErrorCodes.WJSC002)

    @staticmethod
    def file_rejected(message: str = None):
        logger.error(ErrorCodes.WJSC003)
        return create_http_exception(ErrorCodes.WJSC003, message)

    @staticmethod
    def file_format_unsupported():
        logger.error(ErrorCodes.WJSC004)
        return create_http_exception(ErrorCodes.WJSC004)

    @staticmethod
    def file_size_exceeded():
        logger.error(ErrorCodes.WJSC005)
        return create_http_exception(ErrorCodes.WJSC005)

    @staticmethod
    def project_plan_type_invalid():
        logger.error(ErrorCodes.WJSC006)
        return create_http_exception(ErrorCodes.WJSC006)

    @staticmethod
    def unauthorized():
        logger.error(ErrorCodes.WJSC007)
        return create_http_exception(ErrorCodes.WJSC007)
    
    @staticmethod
    def invalid_user():
        logger.error(ErrorCodes.WJSC008)
        return create_http_exception(ErrorCodes.WJSC008)
    


    @staticmethod
    def task_already_exists():
        logger.error(ErrorCodes.WJSC010)
        return create_http_exception(ErrorCodes.WJSC010)

    
    @staticmethod
    def invalid_parameters():
        logger.error(ErrorCodes.WJSC009)
        return create_http_exception(ErrorCodes.WJSC009)

    @staticmethod
    def internal_error(original_error: Exception):
        logger.error(ErrorCodes.WJSC011)
        return create_server_error("WJSC011", original_error)


class LaunchReviewErrors:
    """启动审查接口错误"""

    @staticmethod
    def missing_parameters():
        logger.error(ErrorCodes.QDSC001)
        return create_http_exception(ErrorCodes.QDSC001)

    @staticmethod
    def invalid_param_format():
        logger.error(ErrorCodes.QDSC002)
        return create_http_exception(ErrorCodes.QDSC002)

    @staticmethod
    def unauthorized():
        logger.error(ErrorCodes.QDSC003)
        return create_http_exception(ErrorCodes.QDSC003)

    @staticmethod
    def invalid_user():
        logger.error(ErrorCodes.QDSC004)
        return create_http_exception(ErrorCodes.QDSC004)

    @staticmethod
    def task_not_found():
        logger.error(ErrorCodes.QDSC005)
        return create_http_exception(ErrorCodes.QDSC005)

    @staticmethod
    def task_already_exists():
        logger.error(ErrorCodes.QDSC006)
        return create_http_exception(ErrorCodes.QDSC006)

    @staticmethod
    def project_plan_type_invalid():
        logger.error(ErrorCodes.QDSC007)
        return create_http_exception(ErrorCodes.QDSC007)

    @staticmethod
    def enum_type_invalid():
        logger.error(ErrorCodes.QDSC008)
        return create_http_exception(ErrorCodes.QDSC008)

    @staticmethod
    def enum_type_cannot_be_null():
        logger.error(ErrorCodes.QDSC009)
        return create_http_exception(ErrorCodes.QDSC009)

    @staticmethod
    def file_info_not_found(original_error: Exception):
        logger.error(ErrorCodes.QDSC010)
        return create_server_error("QDSC010", original_error)

    @staticmethod
    def internal_error(original_error: Exception):
        logger.error(ErrorCodes.QDSC011)
        return create_server_error("QDSC011", original_error)

    @staticmethod
    def task_not_found_or_expired():
        logger.error(ErrorCodes.QDSC012)
        return create_http_exception(ErrorCodes.QDSC012)

    @staticmethod
    def file_info_not_found():
        logger.error(ErrorCodes.QDSC013)
        return create_http_exception(ErrorCodes.QDSC013)

    @staticmethod
    def tendency_review_role_invalid():
        logger.error(ErrorCodes.QDSC014)
        return create_http_exception(ErrorCodes.QDSC014)

    @staticmethod
    def invalid_review_item_format(invalid_items: list = None):
        """审查项配置格式错误"""
        logger.error(f"审查项配置格式错误: {invalid_items}")
        message = f"审查项配置格式错误，必须为「chapter_code_review_dimension」格式（如 basis_sensitive_word_check）。无效项: {invalid_items}"
        return create_http_exception(ErrorCodes.QDSC015, message)

    @staticmethod
    def invalid_chapter_code(invalid_codes: list = None):
        """章节code不支持"""
        logger.error(f"章节code不支持: {invalid_codes}")
        message = f"章节code不支持。无效的章节code: {invalid_codes}"
        return create_http_exception(ErrorCodes.QDSC016, message)

    @staticmethod
    def invalid_review_dimension(invalid_dimensions: list = None):
        """审查项code不支持"""
        logger.error(f"审查项code不支持: {invalid_dimensions}")
        message = f"审查项code不支持。无效的审查项code: {invalid_dimensions}"
        return create_http_exception(ErrorCodes.QDSC017, message)

    @staticmethod
    def mutually_exclusive_config():
        """review_config与review_item_config互斥"""
        logger.error("review_config与review_item_config同时提供，但两者互斥")
        message = "参数错误：review_config（审查维度列表）与review_item_config（章节_审查维度列表）互斥，只能提供其中一个，不能同时提供。"
        return create_http_exception(ErrorCodes.QDSC018, message)

    @staticmethod
    def review_config_required():
        """必须提供review_config或review_item_config"""
        logger.error("未提供review_config或review_item_config")
        message = "参数错误：必须提供review_config（审查维度列表）或review_item_config（章节_审查维度列表）中的其中一个。"
        return create_http_exception(ErrorCodes.QDSC019, message)

    @staticmethod
    def duplicate_review_items(duplicates: list = None):
        """审查项配置中存在重复项"""
        logger.error(f"审查项配置中存在重复项: {duplicates}")
        message = f"参数错误：review_item_config 中存在重复的审查项。重复项: {duplicates}"
        return create_http_exception(ErrorCodes.QDSC020, message)

    @staticmethod
    def catalogue_completeness_only(invalid_items: list = None):
        """目录章节仅支持完整性审查"""
        logger.error(f"目录章节使用了非完整性审查: {invalid_items}")
        message = f"参数错误：目录章节（catalogue）仅支持完整性审查（completeness_check）。无效配置项: {invalid_items}"
        return create_http_exception(ErrorCodes.QDSC021, message)


class ReviewResultsErrors:
    """审查结果接口错误"""

    @staticmethod
    def invalid_type():
        logger.error(ErrorCodes.SCJG001)
        return create_http_exception(ErrorCodes.SCJG001)

    @staticmethod
    def missing_param_id():
        logger.error(ErrorCodes.SCJG002)
        return create_http_exception(ErrorCodes.SCJG002)

    @staticmethod
    def invalid_id_format():
        logger.error(ErrorCodes.SCJG003)
        return create_http_exception(ErrorCodes.SCJG003)

    @staticmethod
    def unauthorized():
        logger.error(ErrorCodes.SCJG004)
        return create_http_exception(ErrorCodes.SCJG004)

    @staticmethod
    def invalid_user():
        logger.error(ErrorCodes.SCJG005)
        return create_http_exception(ErrorCodes.SCJG005)

    @staticmethod
    def task_not_found():
        logger.error(ErrorCodes.SCJG006)
        return create_http_exception(ErrorCodes.SCJG006)

    @staticmethod
    def no_review_results():
        logger.error(ErrorCodes.SCJG007)
        return create_http_exception(ErrorCodes.SCJG007)

    @staticmethod
    def server_error(original_error: Exception):
        logger.error(ErrorCodes.SCJG008)
        return create_server_error("SCJG008", original_error)


