package com.narutohuo.xindazhou.common.network

import android.util.Log
import retrofit2.Response
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.UnknownHostException
import java.net.SocketTimeoutException

/**
 * API 基础远程数据源
 * 
 * 封装通用网络请求逻辑，统一处理：
 * - 错误处理和异常捕获
 * - 日志记录
 * - 线程切换（自动切换到 IO 线程）
 * - 网络异常友好提示
 * 
 * 使用方式：
 * ```kotlin
 * class AuthRemoteDataSource : ApiBaseRemoteDataSource() {
 *     private val authApi: AuthApi = ApiManager.create()
 *     
 *     suspend fun login(request: LoginRequest): Result<LoginResponse> {
 *         return executeRequest(
 *             request = { authApi.login(request) },
 *             errorMessage = "登录失败"
 *         )
 *     }
 * }
 * ```
 */
abstract class ApiBaseRemoteDataSource {
    
    /**
     * 获取日志标签（子类可重写）
     * 
     * 注意：必须使用 public，因为内联函数需要访问此属性
     * 内联函数会将代码复制到调用处，如果使用 protected/private 会导致访问权限错误
     */
    open val tag: String
        get() = this::class.simpleName ?: "ApiBaseRemoteDataSource"
    
    /**
     * 处理网络请求（通用方法）
     * 
     * 自动处理：
     * - HTTP 错误码
     * - 业务错误码
     * - 网络异常
     * - 超时异常
     * - 日志记录
     * 
     * @param request 网络请求的 suspend 函数
     * @param errorMessage 错误消息前缀
     * @return Result<T>
     */
    protected suspend inline fun <reified T> executeRequest(
        crossinline request: suspend () -> Response<ApiCommonResult<T>>,
        errorMessage: String = "请求失败"
    ): Result<T> = withContext(Dispatchers.IO) {
        try {
            Log.d(tag, "开始请求: ${T::class.simpleName}")
            val response = request()
            
            // 使用 reified 泛型，自动获取 Class
            ApiResponseParser.handleResponse(
                response = response,
                dataClass = T::class.java,
                tag = tag,
                errorMessage = errorMessage
            )
        } catch (e: SocketTimeoutException) {
            val errorMsg = "请求超时，请检查网络连接"
            Log.e(tag, errorMsg, e)
            Result.failure(Exception(errorMsg))
        } catch (e: UnknownHostException) {
            val errorMsg = "网络连接失败，请检查网络设置"
            Log.e(tag, errorMsg, e)
            Result.failure(Exception(errorMsg))
        } catch (e: Exception) {
            val errorMsg = e.message ?: errorMessage
            Log.e(tag, "请求异常: $errorMsg", e)
            Result.failure(Exception(errorMsg))
        }
    }
    
    /**
     * 处理可空数据的网络请求
     * 
     * 用于处理服务器可能返回 null 的情况
     * 
     * @param request 网络请求的 suspend 函数
     * @param errorMessage 错误消息前缀
     * @return Result<T?>
     */
    protected suspend inline fun <reified T> executeNullableRequest(
        crossinline request: suspend () -> Response<ApiCommonResult<T>>,
        errorMessage: String = "请求失败"
    ): Result<T?> = withContext(Dispatchers.IO) {
        try {
            Log.d(tag, "开始请求（可空）: ${T::class.simpleName}")
            val response = request()
            
            ApiResponseParser.handleNullableResponse(
                response = response,
                tag = tag,
                errorMessage = errorMessage
            )
        } catch (e: SocketTimeoutException) {
            val errorMsg = "请求超时，请检查网络连接"
            Log.e(tag, errorMsg, e)
            Result.failure(Exception(errorMsg))
        } catch (e: UnknownHostException) {
            val errorMsg = "网络连接失败，请检查网络设置"
            Log.e(tag, errorMsg, e)
            Result.failure(Exception(errorMsg))
        } catch (e: Exception) {
            val errorMsg = e.message ?: errorMessage
            Log.e(tag, "请求异常: $errorMsg", e)
            Result.failure(Exception(errorMsg))
        }
    }
}

