package com.narutohuo.xindazhou.common.network.exception

/**
 * API 异常基类
 * 
 * 所有网络相关异常的统一基类
 * 用于区分业务异常和其他异常
 */
sealed class ApiException(
    message: String,
    cause: Throwable? = null
) : Exception(message, cause) {
    
    /**
     * 获取用户友好的错误消息
     */
    abstract fun getUserMessage(): String
}

/**
 * 网络异常（网络连接问题）
 * 
 * 例如：无网络、超时、DNS 解析失败等
 */
class NetworkException(
    message: String = "网络连接失败，请检查网络设置",
    cause: Throwable? = null
) : ApiException(message, cause) {
    
    override fun getUserMessage(): String = message ?: "网络连接失败，请检查网络设置"
}

/**
 * HTTP 异常（HTTP 状态码错误）
 * 
 * 例如：404、500、502 等 HTTP 错误状态码
 */
class HttpException(
    val code: Int,
    message: String? = null,
    cause: Throwable? = null
) : ApiException(
    message ?: "HTTP 请求失败 (状态码: $code)",
    cause
) {
    
    override fun getUserMessage(): String {
        return when (code) {
            400 -> "请求参数错误"
            401 -> "未授权，请重新登录"
            403 -> "无权限访问"
            404 -> "请求的资源不存在"
            500 -> "服务器内部错误"
            502 -> "网关错误"
            503 -> "服务不可用"
            else -> message ?: "请求失败（错误码: $code）"
        }
    }
}

/**
 * 业务异常（业务状态码错误）
 * 
 * 例如：登录失败、参数校验失败等业务层面的错误
 */
class BusinessException(
    val code: Int,
    message: String? = null,
    cause: Throwable? = null
) : ApiException(
    message ?: "操作失败（错误码: $code）",
    cause
) {
    
    companion object {
        // 常见的业务错误码（可根据实际后端定义调整）
        const val CODE_TOKEN_EXPIRED = 401
        const val CODE_TOKEN_INVALID = 402
        const val CODE_PERMISSION_DENIED = 403
        const val CODE_PARAM_ERROR = 400
    }
    
    // 保存原始消息（用于 getUserMessage）
    private val userMessage: String? = message
    
    override fun getUserMessage(): String {
        // 如果后端返回了友好的错误消息，优先使用
        if (!userMessage.isNullOrBlank()) {
            return userMessage
        }
        
        // 否则根据错误码返回默认消息
        return when (code) {
            CODE_TOKEN_EXPIRED -> "登录已过期，请重新登录"
            CODE_TOKEN_INVALID -> "登录凭证无效，请重新登录"
            CODE_PERMISSION_DENIED -> "无权限执行此操作"
            CODE_PARAM_ERROR -> "请求参数错误"
            else -> "操作失败（错误码: $code）"
        }
    }
    
    /**
     * 判断是否是 Token 相关错误
     */
    fun isTokenError(): Boolean {
        return code == CODE_TOKEN_EXPIRED || code == CODE_TOKEN_INVALID
    }
}

/**
 * 数据解析异常
 * 
 * 例如：JSON 解析失败、数据类型转换错误等
 */
class ParseException(
    message: String = "数据解析失败",
    cause: Throwable? = null
) : ApiException(message, cause) {
    
    override fun getUserMessage(): String = "服务器返回数据格式错误，请稍后重试"
}

/**
 * 未知异常（兜底异常）
 * 
 * 用于包装无法明确分类的异常
 */
class UnknownApiException(
    message: String,
    cause: Throwable? = null
) : ApiException(message, cause) {
    
    override fun getUserMessage(): String = message ?: "操作失败"
}

