package com.narutohuo.xindazhou.common.networkrx

import io.reactivex.observers.DisposableObserver

/**
 * RxJava异常处理器
 * 
 * 统一处理RxJava网络请求中的异常
 * 
 * 功能：
 * - 统一的异常处理
 * - 错误码解析
 * - 网络错误处理
 * - 业务错误处理
 * 
 * 使用方式：
 * ```kotlin
 * apiService.login(request)
 *     .compose(RxApiResponseTransformer.transform())
 *     .subscribe(object : RxApiObserver<LoginResponse>() {
 *         override fun onSuccess(data: LoginResponse) {
 *             // 处理成功
 *         }
 *         
 *         override fun onError(code: Int, message: String) {
 *             // 处理错误
 *         }
 *     })
 * ```
 */

/**
 * API响应观察者
 * 
 * 简化API响应的处理
 */
abstract class RxApiObserver<T> : DisposableObserver<RxApiResponse<T>>() {
    
    override fun onNext(response: RxApiResponse<T>) {
        when (response) {
            is RxApiResponse.Success -> {
                onSuccess(response.data)
            }
            is RxApiResponse.Error -> {
                onError(response.code, response.message)
                onError(response)
            }
        }
    }
    
    override fun onError(e: Throwable) {
        // 这里不会被调用，因为错误已经在转换器中处理了
        onError(-1, e.message ?: "未知错误")
    }
    
    override fun onComplete() {
        // 完成回调
    }
    
    /**
     * 成功回调
     * 
     * @param data 响应数据
     */
    abstract fun onSuccess(data: T)
    
    /**
     * 错误回调
     * 
     * @param code 错误码
     * @param message 错误消息
     */
    open fun onError(code: Int, message: String) {
        // 默认实现，子类可以覆盖
    }
    
    /**
     * 错误回调（完整错误信息）
     * 
     * @param error 错误响应
     */
    open fun onError(error: RxApiResponse.Error<T>) {
        // 默认实现，子类可以覆盖
    }
}

/**
 * 简单的API响应回调
 * 
 * 适用于不需要处理错误的场景
 */
class SimpleRxApiObserver<T>(
    private val onSuccess: (T) -> Unit,
    private val onError: ((Int, String) -> Unit)? = null
) : RxApiObserver<T>() {
    
    override fun onSuccess(data: T) {
        onSuccess.invoke(data)
    }
    
    override fun onError(code: Int, message: String) {
        onError?.invoke(code, message)
    }
}

/**
 * 网络异常类型
 */
enum class NetworkErrorType {
    /** 网络错误 */
    NETWORK_ERROR,
    /** 服务器错误 */
    SERVER_ERROR,
    /** Token过期 */
    TOKEN_EXPIRED,
    /** 业务错误 */
    BUSINESS_ERROR,
    /** 未知错误 */
    UNKNOWN_ERROR
}

/**
 * 异常处理工具
 */
object RxExceptionHandler {
    
    /**
     * 处理异常
     * 
     * @param throwable 异常
     * @return 错误信息
     */
    fun handleException(throwable: Throwable): Pair<Int, String> {
        return when (throwable) {
            is java.net.SocketTimeoutException -> {
                Pair(-1, "网络超时，请检查网络连接")
            }
            is java.net.ConnectException -> {
                Pair(-1, "网络连接失败，请检查网络连接")
            }
            is java.net.UnknownHostException -> {
                Pair(-1, "无法连接到服务器，请检查网络连接")
            }
            is retrofit2.HttpException -> {
                val code = throwable.code()
                val message = when (code) {
                    400 -> "请求参数错误"
                    401 -> "未授权，请重新登录"
                    403 -> "禁止访问"
                    404 -> "请求的资源不存在"
                    500 -> "服务器内部错误"
                    502 -> "网关错误"
                    503 -> "服务不可用"
                    504 -> "网关超时"
                    else -> "HTTP错误：$code"
                }
                Pair(code, message)
            }
            else -> {
                Pair(-1, throwable.message ?: "未知错误")
            }
        }
    }
    
    /**
     * 获取错误类型
     * 
     * @param throwable 异常
     * @return 错误类型
     */
    fun getErrorType(throwable: Throwable): NetworkErrorType {
        return when (throwable) {
            is java.net.SocketTimeoutException,
            is java.net.ConnectException,
            is java.net.UnknownHostException -> {
                NetworkErrorType.NETWORK_ERROR
            }
            is retrofit2.HttpException -> {
                when (throwable.code()) {
                    401 -> NetworkErrorType.TOKEN_EXPIRED
                    in 500..599 -> NetworkErrorType.SERVER_ERROR
                    else -> NetworkErrorType.BUSINESS_ERROR
                }
            }
            else -> {
                NetworkErrorType.UNKNOWN_ERROR
            }
        }
    }
}