"""
Error response models for API documentation
Story 3.6: Documentation OpenAPI (Swagger + ReDoc)
"""

from enum import Enum
from pydantic import BaseModel, Field
from typing import Optional, Dict, Any


class ErrorCode(str, Enum):
    """All error codes used in the API"""
    
    # Client errors (4xx)
    INVALID_FORMAT = "INVALID_FORMAT"
    CORRUPTED_FILE = "CORRUPTED_FILE"
    FILE_TOO_LARGE = "FILE_TOO_LARGE"
    URL_DOWNLOAD_FAILED = "URL_DOWNLOAD_FAILED"
    URL_UNREACHABLE = "URL_UNREACHABLE"
    QUOTA_EXCEEDED = "QUOTA_EXCEEDED"
    UNAUTHORIZED = "UNAUTHORIZED"
    FORBIDDEN = "FORBIDDEN"
    INVALID_CREDENTIALS = "INVALID_CREDENTIALS"
    USER_NOT_FOUND = "USER_NOT_FOUND"
    EMAIL_EXISTS = "EMAIL_EXISTS"
    INVALID_EMAIL = "INVALID_EMAIL"
    TOKEN_EXPIRED = "TOKEN_EXPIRED"
    TOKEN_MISSING = "TOKEN_MISSING"
    TOKEN_INVALID = "TOKEN_INVALID"
    MISSING_API_KEY = "MISSING_API_KEY"
    INVALID_API_KEY = "INVALID_API_KEY"
    API_KEY_REVOKED = "API_KEY_REVOKED"
    API_KEY_NOT_FOUND = "API_KEY_NOT_FOUND"
    API_KEY_LIMIT_REACHED = "API_KEY_LIMIT_REACHED"
    PRO_FEATURE_REQUIRED = "PRO_FEATURE_REQUIRED"
    GLOSSARY_NOT_FOUND = "GLOSSARY_NOT_FOUND"
    PROMPT_NOT_FOUND = "PROMPT_NOT_FOUND"
    INVALID_WEBHOOK_URL = "INVALID_WEBHOOK_URL"
    FILE_EXPIRED = "FILE_EXPIRED"
    NOT_READY = "NOT_READY"
    NOT_FOUND = "NOT_FOUND"
    INVALID_REQUEST = "INVALID_REQUEST"
    INVALID_JOB_ID = "INVALID_JOB_ID"
    ACCESS_DENIED = "ACCESS_DENIED"
    
    # Provider errors (5xx but not 500)
    PROVIDER_UNAVAILABLE = "PROVIDER_UNAVAILABLE"
    PROVIDER_RATE_LIMITED = "PROVIDER_RATE_LIMITED"
    ALL_PROVIDERS_FAILED = "ALL_PROVIDERS_FAILED"
    WEBHOOK_FAILED = "WEBHOOK_FAILED"
    
    # System errors (5xx)
    INTERNAL_ERROR = "INTERNAL_ERROR"
    AUTH_HASHING_UNAVAILABLE = "AUTH_HASHING_UNAVAILABLE"


class ErrorResponse(BaseModel):
    """Standard error response format"""
    
    error: ErrorCode = Field(
        ..., 
        description="Code d'erreur standardisé",
        example="INVALID_FORMAT"
    )
    message: str = Field(
        ..., 
        description="Message d'erreur lisible en français",
        example="Format de fichier non supporté. Formats acceptés: .xlsx, .docx, .pptx"
    )
    details: Optional[Dict[str, Any]] = Field(
        None, 
        description="Détails supplémentaires sur l'erreur"
    )

    class Config:
        json_schema_extra = {
            "example": {
                "error": "INVALID_FORMAT",
                "message": "Format PDF non supporté. Formats acceptés: .xlsx, .docx, .pptx",
                "details": {
                    "accepted_formats": [".xlsx", ".docx", ".pptx"],
                    "detected_format": ".pdf"
                }
            }
        }


# Pre-defined error examples for OpenAPI documentation
ERROR_EXAMPLES = {
    "INVALID_FORMAT": {
        "summary": "Format de fichier non supporté",
        "value": {
            "error": "INVALID_FORMAT",
            "message": "Format PDF non supporté. Formats acceptés: .xlsx, .docx, .pptx",
            "details": {
                "accepted_formats": [".xlsx", ".docx", ".pptx"],
                "detected_format": ".pdf"
            }
        }
    },
    "CORRUPTED_FILE": {
        "summary": "Fichier corrompu",
        "value": {
            "error": "CORRUPTED_FILE",
            "message": "Le fichier n'est pas un document Office valide ou est corrompu.",
            "details": {
                "reason": "Invalid magic bytes"
            }
        }
    },
    "FILE_TOO_LARGE": {
        "summary": "Fichier trop volumineux",
        "value": {
            "error": "FILE_TOO_LARGE",
            "message": "Le fichier dépasse la limite de 50 MB.",
            "details": {
                "max_size_mb": 50,
                "actual_size_mb": 65.3
            }
        }
    },
    "QUOTA_EXCEEDED": {
        "summary": "Limite quotidienne atteinte",
        "value": {
            "error": "QUOTA_EXCEEDED",
            "message": "Limite quotidienne de 5 traductions atteinte. Réessayez après minuit UTC.",
            "details": {
                "current_usage": 5,
                "limit": 5,
                "tier": "free",
                "reset_at": "2024-01-16T00:00:00Z"
            }
        }
    },
    "UNAUTHORIZED": {
        "summary": "Authentification requise",
        "value": {
            "error": "UNAUTHORIZED",
            "message": "Authentification requise.",
            "details": None
        }
    },
    "FORBIDDEN": {
        "summary": "Accès interdit",
        "value": {
            "error": "FORBIDDEN",
            "message": "Vous n'avez pas accès à cette ressource.",
            "details": None
        }
    },
    "INVALID_CREDENTIALS": {
        "summary": "Identifiants invalides",
        "value": {
            "error": "INVALID_CREDENTIALS",
            "message": "Email ou mot de passe incorrect.",
            "details": None
        }
    },
    "EMAIL_EXISTS": {
        "summary": "Email déjà utilisé",
        "value": {
            "error": "EMAIL_EXISTS",
            "message": "Un compte existe déjà avec cette adresse email.",
            "details": None
        }
    },
    "TOKEN_EXPIRED": {
        "summary": "Token expiré",
        "value": {
            "error": "TOKEN_EXPIRED",
            "message": "Token invalide ou expiré.",
            "details": None
        }
    },
    "PRO_FEATURE_REQUIRED": {
        "summary": "Fonctionnalité Pro requise",
        "value": {
            "error": "PRO_FEATURE_REQUIRED",
            "message": "Cette fonctionnalité nécessite un abonnement Pro.",
            "details": {
                "feature": "llm_translation",
                "current_tier": "free",
                "required_tier": "pro"
            }
        }
    },
    "API_KEY_NOT_FOUND": {
        "summary": "Clé API non trouvée",
        "value": {
            "error": "API_KEY_NOT_FOUND",
            "message": "Clé API non trouvée, n'appartient pas à l'utilisateur ou déjà révoquée.",
            "details": None
        }
    },
    "FILE_EXPIRED": {
        "summary": "Fichier expiré",
        "value": {
            "error": "FILE_EXPIRED",
            "message": "Le fichier traduit n'est plus disponible ou a expiré.",
            "details": {
                "job_id": "tr_abc123",
                "status": "not_found"
            }
        }
    },
    "NOT_READY": {
        "summary": "Traduction en cours",
        "value": {
            "error": "NOT_READY",
            "message": "La traduction est encore en cours.",
            "details": {
                "job_id": "tr_abc123",
                "status": "processing",
                "progress_percent": 45
            }
        }
    },
    "NOT_FOUND": {
        "summary": "Ressource non trouvée",
        "value": {
            "error": "NOT_FOUND",
            "message": "Ressource non trouvée.",
            "details": None
        }
    },
    "INTERNAL_ERROR": {
        "summary": "Erreur interne",
        "value": {
            "error": "INTERNAL_ERROR",
            "message": "Une erreur interne est survenue. Veuillez réessayer.",
            "details": None
        }
    },
    "INVALID_WEBHOOK_URL": {
        "summary": "URL webhook invalide",
        "value": {
            "error": "INVALID_WEBHOOK_URL",
            "message": "L'URL du webhook doit être une URL HTTP/HTTPS valide.",
            "details": {
                "field": "webhook_url",
                "allowed_schemes": ["http", "https"],
                "hint": "L'URL doit commencer par http:// ou https://"
            }
        }
    },
    "WEBHOOK_LOCALHOST_BLOCKED": {
        "summary": "Localhost non autorisé",
        "value": {
            "error": "INVALID_WEBHOOK_URL",
            "message": "Les URLs localhost ne sont pas autorisées.",
            "details": {
                "field": "webhook_url",
                "reason": "localhost_blocked"
            }
        }
    },
    "WEBHOOK_PRIVATE_IP_BLOCKED": {
        "summary": "IP privée non autorisée",
        "value": {
            "error": "INVALID_WEBHOOK_URL",
            "message": "Les adresses IP privées ne sont pas autorisées.",
            "details": {
                "field": "webhook_url",
                "reason": "private_ip_blocked"
            }
        }
    },
    "WEBHOOK_CREDENTIALS_IN_URL": {
        "summary": "Credentials dans l'URL",
        "value": {
            "error": "INVALID_WEBHOOK_URL",
            "message": "L'URL ne doit pas contenir d'identifiants (credentials).",
            "details": {
                "field": "webhook_url",
                "reason": "credentials_in_url"
            }
        }
    }
}
