"""
统一错误处理模块

定义应用级错误码、异常类和错误响应格式
"""
from enum import Enum
from typing import Optional, Dict, Any


class ErrorCode(str, Enum):
    """统一错误码
    
    格式：4位数字
    - 0000: 成功
    - 1xxx: 通用错误
    - 2xxx: 业务错误
    - 3xxx: 任务错误
    - 4xxx: AI 服务错误
    - 5xxx: 存储错误
    """
    
    # 成功
    SUCCESS = "0000"
    
    # 通用错误 (1xxx)
    UNKNOWN_ERROR = "1000"
    INVALID_PARAMETER = "1001"
    UNAUTHORIZED = "1002"
    FORBIDDEN = "1003"
    NOT_FOUND = "1004"
    METHOD_NOT_ALLOWED = "1005"
    CONFLICT = "1006"
    RATE_LIMIT_EXCEEDED = "1007"
    SERVICE_UNAVAILABLE = "1008"

    # 业务错误 (2xxx)
    PROJECT_NOT_FOUND = "2001"
    PROJECT_CREATE_FAILED = "2002"
    PROJECT_UPDATE_FAILED = "2003"
    PROJECT_DELETE_FAILED = "2004"
    
    ASSET_NOT_FOUND = "2011"
    ASSET_CREATE_FAILED = "2012"
    ASSET_UPDATE_FAILED = "2013"
    ASSET_DELETE_FAILED = "2014"
    
    CANVAS_NOT_FOUND = "2021"
    CANVAS_SAVE_FAILED = "2022"
    
    EPISODE_NOT_FOUND = "2031"
    STORYBOARD_NOT_FOUND = "2032"
    
    # 任务错误 (3xxx)
    TASK_CREATE_FAILED = "3001"
    TASK_NOT_FOUND = "3002"
    TASK_TIMEOUT = "3003"
    TASK_EXECUTION_FAILED = "3004"
    TASK_CANCELLED = "3005"
    TASK_QUEUE_FULL = "3006"
    
    # AI 服务错误 (4xxx)
    MODEL_NOT_FOUND = "4001"
    MODEL_NOT_AVAILABLE = "4002"
    GENERATION_FAILED = "4003"
    QUOTA_EXCEEDED = "4004"
    INVALID_PROMPT = "4005"
    PROVIDER_ERROR = "4006"
    
    # 存储错误 (5xxx)
    STORAGE_ERROR = "5001"
    FILE_NOT_FOUND = "5002"
    UPLOAD_FAILED = "5003"
    DOWNLOAD_FAILED = "5004"
    FILE_TOO_LARGE = "5005"
    INVALID_FILE_TYPE = "5006"


class AppException(Exception):
    """应用基础异常类
    
    所有自定义异常都应该继承此类。这是领域异常的根类，
    不包含任何HTTP相关的概念，可以在任何层使用。
    """
    
    def __init__(
        self,
        code: ErrorCode,
        message: str,
        details: Optional[Dict[str, Any]] = None,
        status_code: int = 400
    ):
        """
        Args:
            code: 错误码
            message: 错误消息（用户友好）
            details: 错误详情（用于调试）
            status_code: HTTP 状态码（仅用于API层转换）
        """
        self.code = code
        self.message = message
        self.details = details or {}
        self.status_code = status_code
        super().__init__(message)
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            "code": self.code.value if isinstance(self.code, ErrorCode) else self.code,
            "message": self.message,
            "details": self.details
        }


class BusinessException(AppException):
    """业务异常（4xx）
    
    用于业务逻辑错误，如资源不存在、参数无效等
    """
    
    def __init__(
        self,
        code: ErrorCode,
        message: str,
        details: Optional[Dict[str, Any]] = None
    ):
        super().__init__(code, message, details, status_code=400)


class SystemException(AppException):
    """系统异常（5xx）
    
    用于系统级错误，如数据库连接失败、外部服务不可用等
    """
    
    def __init__(
        self,
        code: ErrorCode,
        message: str,
        details: Optional[Dict[str, Any]] = None
    ):
        super().__init__(code, message, details, status_code=500)


# ============================================================================
# 便捷异常类 - 常用业务异常
# ============================================================================

class InvalidParameterException(BusinessException):
    """参数无效异常"""
    
    def __init__(self, field: str, reason: str):
        super().__init__(
            ErrorCode.INVALID_PARAMETER,
            f"Invalid parameter: {field}",
            {"field": field, "reason": reason}
        )


class ResourceNotFoundException(BusinessException):
    """资源不存在异常"""
    
    def __init__(self, resource_type: str, resource_id: str):
        super().__init__(
            ErrorCode.NOT_FOUND,
            f"{resource_type} not found",
            {"resource_type": resource_type, "resource_id": resource_id}
        )


class ProjectNotFoundException(BusinessException):
    """项目不存在异常"""
    
    def __init__(self, project_id: str):
        super().__init__(
            ErrorCode.PROJECT_NOT_FOUND,
            "Project not found",
            {"project_id": project_id}
        )


class AssetNotFoundException(BusinessException):
    """资产不存在异常"""
    
    def __init__(self, asset_id: str):
        super().__init__(
            ErrorCode.ASSET_NOT_FOUND,
            "Asset not found",
            {"asset_id": asset_id}
        )


class CanvasNotFoundException(BusinessException):
    """画布不存在异常"""
    
    def __init__(self, canvas_id: str):
        super().__init__(
            ErrorCode.CANVAS_NOT_FOUND,
            "Canvas not found",
            {"canvas_id": canvas_id}
        )


class TaskNotFoundException(BusinessException):
    """任务不存在异常"""
    
    def __init__(self, task_id: str):
        super().__init__(
            ErrorCode.TASK_NOT_FOUND,
            "Task not found",
            {"task_id": task_id}
        )


class TaskTimeoutException(SystemException):
    """任务超时异常"""
    
    def __init__(self, task_id: str, timeout: int):
        super().__init__(
            ErrorCode.TASK_TIMEOUT,
            "Task execution timeout",
            {"task_id": task_id, "timeout_seconds": timeout}
        )


class TaskQueueFullException(SystemException):
    """任务队列已满异常"""
    
    def __init__(self, queue_size: int):
        super().__init__(
            ErrorCode.TASK_QUEUE_FULL,
            "Task queue is full, please try again later",
            {"queue_size": queue_size}
        )


class ModelNotFoundException(BusinessException):
    """模型不存在异常"""
    
    def __init__(self, model_id: str):
        super().__init__(
            ErrorCode.MODEL_NOT_FOUND,
            "Model not found or not configured",
            {"model_id": model_id}
        )


class GenerationFailedException(SystemException):
    """生成失败异常"""
    
    def __init__(self, reason: str, provider: Optional[str] = None):
        super().__init__(
            ErrorCode.GENERATION_FAILED,
            "Generation failed",
            {"reason": reason, "provider": provider}
        )


class StorageException(SystemException):
    """存储异常"""
    
    def __init__(self, operation: str, reason: str):
        super().__init__(
            ErrorCode.STORAGE_ERROR,
            f"Storage {operation} failed",
            {"operation": operation, "reason": reason}
        )


class FileNotFoundException(BusinessException):
    """文件不存在异常"""
    
    def __init__(self, file_path: str):
        super().__init__(
            ErrorCode.FILE_NOT_FOUND,
            "File not found",
            {"file_path": file_path}
        )


class RateLimitExceededException(BusinessException):
    """速率限制异常"""
    
    def __init__(self, limit: int, window: int):
        super().__init__(
            ErrorCode.RATE_LIMIT_EXCEEDED,
            "Rate limit exceeded",
            {"limit": limit, "window_seconds": window}
        )
        self.status_code = 429


class CacheException(SystemException):
    """缓存异常"""
    
    def __init__(self, operation: str, reason: str):
        super().__init__(
            ErrorCode.UNKNOWN_ERROR,
            f"Cache {operation} failed",
            {"operation": operation, "reason": reason}
        )


class RateLimitException(BusinessException):
    """速率限制异常"""
    
    def __init__(self, limit: int, window: int, retry_after: int = None):
        details = {"limit": limit, "window_seconds": window}
        if retry_after:
            details["retry_after_seconds"] = retry_after
        
        super().__init__(
            ErrorCode.RATE_LIMIT_EXCEEDED,
            "Rate limit exceeded",
            details
        )
        self.status_code = 429


class EpisodeNotFoundException(BusinessException):
    """剧集不存在异常"""
    
    def __init__(self, episode_id: str):
        super().__init__(
            ErrorCode.EPISODE_NOT_FOUND,
            "Episode not found",
            {"episode_id": episode_id}
        )


class StoryboardNotFoundException(BusinessException):
    """分镜不存在异常"""
    
    def __init__(self, storyboard_id: str):
        super().__init__(
            ErrorCode.STORYBOARD_NOT_FOUND,
            "Storyboard not found",
            {"storyboard_id": storyboard_id}
        )


class ProjectCreateFailedException(SystemException):
    """项目创建失败异常"""
    
    def __init__(self, reason: str):
        super().__init__(
            ErrorCode.PROJECT_CREATE_FAILED,
            "Failed to create project",
            {"reason": reason}
        )


class ProjectUpdateFailedException(SystemException):
    """项目更新失败异常"""
    
    def __init__(self, project_id: str, reason: str):
        super().__init__(
            ErrorCode.PROJECT_UPDATE_FAILED,
            "Failed to update project",
            {"project_id": project_id, "reason": reason}
        )


class ProjectDeleteFailedException(SystemException):
    """项目删除失败异常"""
    
    def __init__(self, project_id: str, reason: str):
        super().__init__(
            ErrorCode.PROJECT_DELETE_FAILED,
            "Failed to delete project",
            {"project_id": project_id, "reason": reason}
        )


class TaskExecutionFailedException(SystemException):
    """任务执行失败异常"""
    
    def __init__(self, task_id: str, reason: str):
        super().__init__(
            ErrorCode.TASK_EXECUTION_FAILED,
            "Task execution failed",
            {"task_id": task_id, "reason": reason}
        )


class TaskCancelledException(BusinessException):
    """任务已取消异常"""
    
    def __init__(self, task_id: str):
        super().__init__(
            ErrorCode.TASK_CANCELLED,
            "Task has been cancelled",
            {"task_id": task_id}
        )


class ModelNotAvailableException(BusinessException):
    """模型不可用异常"""
    
    def __init__(self, model_id: str, reason: Optional[str] = None):
        details = {"model_id": model_id}
        if reason:
            details["reason"] = reason
        super().__init__(
            ErrorCode.MODEL_NOT_AVAILABLE,
            "Model is not available",
            details
        )


class QuotaExceededException(BusinessException):
    """配额超限异常"""
    
    def __init__(self, resource: str, limit: int):
        super().__init__(
            ErrorCode.QUOTA_EXCEEDED,
            f"{resource} quota exceeded",
            {"resource": resource, "limit": limit}
        )


class InvalidPromptException(BusinessException):
    """提示词无效异常"""
    
    def __init__(self, reason: str):
        super().__init__(
            ErrorCode.INVALID_PROMPT,
            "Invalid prompt",
            {"reason": reason}
        )


class ProviderErrorException(SystemException):
    """AI提供商错误异常"""
    
    def __init__(self, provider: str, error_message: str):
        super().__init__(
            ErrorCode.PROVIDER_ERROR,
            f"Provider error: {provider}",
            {"provider": provider, "error_message": error_message}
        )


class UploadFailedException(SystemException):
    """上传失败异常"""
    
    def __init__(self, reason: str):
        super().__init__(
            ErrorCode.UPLOAD_FAILED,
            "File upload failed",
            {"reason": reason}
        )


class DownloadFailedException(SystemException):
    """下载失败异常"""
    
    def __init__(self, url: str, reason: str):
        super().__init__(
            ErrorCode.DOWNLOAD_FAILED,
            "File download failed",
            {"url": url, "reason": reason}
        )


class FileTooLargeException(BusinessException):
    """文件过大异常"""
    
    def __init__(self, file_size: int, max_size: int):
        super().__init__(
            ErrorCode.FILE_TOO_LARGE,
            "File size exceeds limit",
            {"file_size_bytes": file_size, "max_size_bytes": max_size}
        )


class InvalidFileTypeException(BusinessException):
    """文件类型无效异常"""
    
    def __init__(self, file_type: str, allowed_types: list):
        super().__init__(
            ErrorCode.INVALID_FILE_TYPE,
            "Invalid file type",
            {"file_type": file_type, "allowed_types": allowed_types}
        )


class UnauthorizedException(BusinessException):
    """未授权异常"""
    
    def __init__(self, reason: Optional[str] = None):
        details = {}
        if reason:
            details["reason"] = reason
        super().__init__(
            ErrorCode.UNAUTHORIZED,
            "Unauthorized access",
            details
        )
        self.status_code = 401


class ForbiddenException(BusinessException):
    """禁止访问异常"""
    
    def __init__(self, reason: Optional[str] = None):
        details = {}
        if reason:
            details["reason"] = reason
        super().__init__(
            ErrorCode.FORBIDDEN,
            "Access forbidden",
            details
        )
        self.status_code = 403


class ConflictException(BusinessException):
    """资源冲突异常"""
    
    def __init__(self, resource_type: str, reason: str):
        super().__init__(
            ErrorCode.CONFLICT,
            f"{resource_type} conflict",
            {"resource_type": resource_type, "reason": reason}
        )
        self.status_code = 409


