use actix_web::{ResponseError, http::StatusCode, HttpResponse};
use serde::Serialize;
use std::fmt;

#[derive(Debug, Serialize)]
pub struct ErrorResponse<T = ()> {
    pub success: bool,
    pub data: Option<T>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<String>,
}

impl<T> ErrorResponse<T> {
    pub fn success(data: T) -> Self {
        Self {
            success: true,
            data: Some(data),
            error: None,
        }
    }

    pub fn error(msg: impl Into<String>) -> Self {
        Self {
            success: false,
            data: None,
            error: Some(msg.into()),
        }
    }
}

impl<T: Serialize> ErrorResponse<T> {
    pub fn to_json_response(self) -> HttpResponse {
        HttpResponse::Ok().json(self)
    }
}

impl ErrorResponse<()> {
    pub fn to_error_response(&self, status: StatusCode) -> HttpResponse {
        let body = serde_json::json!({
            "success": false,
            "error": self.error.clone().unwrap_or_else(|| "Unknown error".to_string())
        });
        HttpResponse::build(status).json(body)
    }
}

#[derive(Debug)]
pub enum AppError {
    Unauthorized(String),
    Forbidden(String),
    NotFound(String),
    BadRequest(String),
    Internal(String),
    Database(String),
    TooManyRequests(String),
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            AppError::Unauthorized(msg) => write!(f, "{}", msg),
            AppError::Forbidden(msg) => write!(f, "{}", msg),
            AppError::NotFound(msg) => write!(f, "{}", msg),
            AppError::BadRequest(msg) => write!(f, "{}", msg),
            AppError::Internal(msg) => write!(f, "{}", msg),
            AppError::Database(msg) => write!(f, "{}", msg),
            AppError::TooManyRequests(msg) => write!(f, "{}", msg),
        }
    }
}

impl ResponseError for AppError {
    fn status_code(&self) -> StatusCode {
        match self {
            AppError::Unauthorized(_) => StatusCode::UNAUTHORIZED,
            AppError::Forbidden(_) => StatusCode::FORBIDDEN,
            AppError::NotFound(_) => StatusCode::NOT_FOUND,
            AppError::BadRequest(_) => StatusCode::BAD_REQUEST,
            AppError::Internal(_) | AppError::Database(_) => StatusCode::INTERNAL_SERVER_ERROR,
            AppError::TooManyRequests(_) => StatusCode::TOO_MANY_REQUESTS,
        }
    }

    fn error_response(&self) -> actix_web::HttpResponse {
        let error_message = self.to_string();
        let status_code = self.status_code().as_u16();

        let html = format!(r#"<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>错误 {status_code}</title>
    <style>
        * {{ margin: 0; padding: 0; box-sizing: border-box; }}
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
        }}
        .container {{
            background: white;
            border-radius: 16px;
            padding: 48px;
            max-width: 480px;
            width: 100%;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            text-align: center;
        }}
        .error-code {{
            font-size: 72px;
            font-weight: bold;
            color: #e74c3c;
            margin-bottom: 16px;
        }}
        h1 {{
            color: #333;
            margin-bottom: 16px;
            font-size: 24px;
        }}
        .message {{
            background: #f8f9fa;
            border-radius: 8px;
            padding: 16px;
            margin: 24px 0;
            color: #555;
            font-size: 14px;
            line-height: 1.6;
        }}
        .hint {{
            color: #888;
            font-size: 13px;
            margin-top: 24px;
        }}
        .back-link {{
            display: inline-block;
            margin-top: 24px;
            padding: 12px 24px;
            background: #3498db;
            color: white;
            text-decoration: none;
            border-radius: 8px;
            font-size: 14px;
            transition: background 0.3s;
        }}
        .back-link:hover {{
            background: #2980b9;
        }}
    </style>
</head>
<body>
    <div class="container">
        <div class="error-code">{status_code}</div>
        <h1>{error_title}</h1>
        <div class="message">{error_message}</div>
        <p style="margin-top: 24px; color: #3498db; font-size: 14px;">请返回小程序重新生成新的下载链接</p>
        <div class="hint">如果问题持续存在，请联系技术支持</div>
    </div>
</body>
</html>"#,
            error_title = match self {
                AppError::Unauthorized(_) => "认证失败",
                AppError::Forbidden(_) => "权限不足",
                AppError::NotFound(_) => "内容未找到",
                AppError::BadRequest(_) => "请求无效",
                AppError::Internal(_) | AppError::Database(_) => "服务器错误",
                AppError::TooManyRequests(_) => "请求过于频繁",
            }
        );

        HttpResponse::build(self.status_code())
            .content_type("text/html; charset=utf-8")
            .body(html)
    }
}

