package com.narutohuo.xindazhou.auth

import android.content.Context
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.narutohuo.xindazhou.auth.datasource.remote.AuthApi
import com.narutohuo.xindazhou.auth.model.LoginRequest
import com.narutohuo.xindazhou.auth.model.LoginResponse
import com.narutohuo.xindazhou.auth.model.RegisterRequest
import com.narutohuo.xindazhou.auth.storage.TokenStore
import com.narutohuo.xindazhou.common.network.ApiManager
import com.narutohuo.xindazhou.common.network.ApiBaseRemoteDataSource
import com.narutohuo.xindazhou.common.network.NetworkManager
import com.narutohuo.xindazhou.core.log.ILog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * 认证管理器
 * 
 * ✅ 直接使用 Network 模块，展示其强大和易用性
 * 
 * 功能：
 * - 用户登录
 * - 用户注册
 * - Token 刷新
 * - 登录状态管理
 * 
 * 使用方式：
 * ```kotlin
 * // 在 Application 中初始化
 * AuthManager.setContext(context)
 * 
 * // 用户登录（一行代码，自动处理所有网络逻辑）
 * AuthManager.login(activity, mobile, password) { result ->
 *     result.onSuccess { response ->
 *         // 登录成功，Token 已自动保存
 *     }
 *     result.onFailure { error ->
 *         // 登录失败，自动错误处理
 *     }
 * }
 * ```
 * 
 * Network 模块提供的强大功能：
 * - ✅ 自动错误处理（HTTP 错误、业务错误、网络异常）
 * - ✅ 自动日志记录
 * - ✅ 自动线程切换（IO 线程）
 * - ✅ 全局处理器（GlobalApiOperator）
 * - ✅ 自动重试（可选）
 * - ✅ 统一响应格式（ApiResponse<T>）
 */
object AuthManager : ApiBaseRemoteDataSource() {
    
    private val TAG = "AuthManager"
    
    // 直接使用 Network 模块创建 API 接口
    private val authApi: AuthApi by lazy {
        ApiManager.create<AuthApi>()  // ← Network 模块的强大功能：一行代码创建接口
    }
    
    private var applicationContext: Context? = null
    private var isInitialized = false
    
    /**
     * 设置应用上下文（懒加载模式）
     */
    fun setContext(context: Context) {
        this.applicationContext = context.applicationContext
        TokenStore.init(context.applicationContext)
        
        // 配置 Network 模块的 Token Provider（自动添加 Token 到请求头）
        ApiManager.setTokenProvider {
            TokenStore.getAccessToken()
        }
        
        // 配置 Network 模块的 Token 刷新 Provider（自动刷新过期的 Token）
        NetworkManager.refreshTokenProvider = {
            refreshTokenIfNeeded()
        }
        
        ILog.d(TAG, "AuthManager context 已设置，Network 模块已配置")
    }
    
    /**
     * 确保已初始化
     */
    private fun ensureInitialized() {
        if (isInitialized) {
            return
        }
        
        val context = applicationContext ?: run {
            throw IllegalStateException("AuthManager context 未设置，请先调用 AuthManager.setContext(context)")
        }
        
        isInitialized = true
        ILog.d(TAG, "AuthManager 初始化完成")
    }
    
    /**
     * 用户登录
     * 
     * ✅ 直接使用 Network 模块的强大功能：
     * - executeRequestResponse() 自动处理所有网络逻辑
     * - 自动错误处理、日志记录、线程切换
     * - 支持自动重试（可选）
     * 
     * @param activity Activity 实例
     * @param mobile 手机号
     * @param password 密码
     * @param onResult 登录结果回调
     */
    fun login(
        activity: FragmentActivity,
        mobile: String,
        password: String,
        onResult: (Result<LoginResponse>) -> Unit
    ) {
        activity.lifecycleScope.launch {
            try {
                ensureInitialized()
                
                // ✅ 使用 Network 模块的强大功能：executeRequestResponse()
                // 自动处理：错误处理、日志记录、线程切换、全局处理器、自动重试
                val result = executeRequestResponse(
                    request = { authApi.login(LoginRequest(mobile, password)) },  // ← 一行代码发起请求
                    enableRetry = true,  // ← 可选：自动重试（Network 模块的强大功能）
                    retryTimes = 3
                ).toResult()  // ← Network 模块的强大功能：自动转换为 Result<T>
                
                // 登录成功，自动保存 Token
                result.onSuccess { response ->
                    TokenStore.saveToken(
                        response.accessToken,
                        response.refreshToken,
                        response.userId
                    )
                    ILog.d(TAG, "登录成功，Token 已自动保存")
                }
                
                onResult(result)
            } catch (e: Exception) {
                ILog.e(TAG, "登录异常", e)
                onResult(Result.failure(e))
            }
        }
    }
    
    /**
     * 用户注册
     * 
     * ✅ 直接使用 Network 模块的强大功能
     */
    fun register(
        activity: FragmentActivity,
        mobile: String,
        password: String,
        onResult: (Result<LoginResponse>) -> Unit
    ) {
        activity.lifecycleScope.launch {
            try {
                ensureInitialized()
                
                // ✅ 使用 Network 模块的强大功能：executeRequestResponse()
                val result = executeRequestResponse(
                    request = { authApi.register(RegisterRequest(mobile, password)) },
                    enableRetry = true,
                    retryTimes = 3
                ).toResult()
                
                // 注册成功，自动保存 Token
                result.onSuccess { response ->
                    TokenStore.saveToken(
                        response.accessToken,
                        response.refreshToken,
                        response.userId
                    )
                    ILog.d(TAG, "注册成功，Token 已自动保存")
                }
                
                onResult(result)
            } catch (e: Exception) {
                ILog.e(TAG, "注册异常", e)
                onResult(Result.failure(e))
            }
        }
    }
    
    /**
     * 刷新 Token
     * 
     * ✅ 直接使用 Network 模块的强大功能
     */
    suspend fun refreshToken(refreshToken: String): Result<LoginResponse> {
        ensureInitialized()
        
        // ✅ 使用 Network 模块的强大功能：executeRequestResponse()
        val result = executeRequestResponse(
            request = { authApi.refreshToken(refreshToken) },
            enableRetry = true,
            retryTimes = 3
        ).toResult()
        
        // 刷新成功，自动保存 Token
        result.onSuccess { response ->
            TokenStore.saveToken(
                response.accessToken,
                response.refreshToken,
                response.userId
            )
            ILog.d(TAG, "Token 刷新成功，已自动保存")
        }
        
        return result
    }
    
    /**
     * 刷新 Token（如果需要）
     * 
     * ✅ 先检查 Token 是否过期，如果未过期则返回当前 Token，过期才刷新
     */
    suspend fun refreshTokenIfNeeded(
        scope: CoroutineScope? = null,
        onResult: ((Result<String?>) -> Unit)? = null
    ): String? {
        // 先检查当前 Token 是否过期
        val currentToken = TokenStore.getAccessToken()
        if (!currentToken.isNullOrEmpty()) {
            val expiresAt = TokenStore.getTokenExpiresAt(currentToken)
            val currentTime = System.currentTimeMillis() / 1000 // 转换为秒
            
            // 如果 Token 未过期（留有 60 秒缓冲），直接返回当前 Token
            if (expiresAt != null && expiresAt > currentTime + 60) {
                ILog.d(TAG, "Token 未过期，无需刷新（过期时间: ${expiresAt - currentTime}秒后）")
                onResult?.invoke(Result.success(currentToken))
                return currentToken
            }
        }
        
        // Token 过期或不存在，需要刷新
        val refreshToken = TokenStore.getRefreshToken()
        if (refreshToken.isNullOrEmpty()) {
            ILog.w(TAG, "RefreshToken 为空，无法刷新")
            onResult?.invoke(Result.failure(Exception("RefreshToken 为空")))
            return null
        }
        
        return try {
            ensureInitialized()
            
            ILog.d(TAG, "Token 已过期或不存在，开始刷新...")
            // ✅ 使用 Network 模块的强大功能：executeRequestResponse()
            val result = refreshToken(refreshToken)
            
            result.getOrNull()?.let { loginResponse ->
                ILog.d(TAG, "Token 刷新成功")
                onResult?.invoke(Result.success(loginResponse.accessToken))
                loginResponse.accessToken
            } ?: run {
                val error = result.exceptionOrNull() ?: Exception("Token 刷新失败")
                ILog.w(TAG, "Token 刷新失败: ${error.message}")
                onResult?.invoke(Result.failure(error))
                null
            }
        } catch (e: Exception) {
            ILog.e(TAG, "Token 刷新异常", e)
            onResult?.invoke(Result.failure(e))
            null
        }
    }
    
    /**
     * 在后台协程中刷新 Token（如果需要）
     */
    fun refreshTokenIfNeededAsync(
        scope: CoroutineScope,
        onResult: ((Result<String?>) -> Unit)? = null
    ) {
        scope.launch(Dispatchers.IO) {
            refreshTokenIfNeeded(scope, onResult)
        }
    }
    
    // ========== 便捷方法 ==========
    
    /**
     * 检查是否已登录（同步，仅检查 Access Token，不刷新）
     */
    fun isLoggedIn(): Boolean {
        return TokenStore.isLoggedIn()
    }
    
    /**
     * 检查是否已登录（异步，支持自动刷新）
     */
    suspend fun isLoggedInAsync(): Boolean {
        val accessToken = TokenStore.getAccessToken()
        
        if (accessToken.isNullOrEmpty()) {
            val refreshToken = TokenStore.getRefreshToken()
            if (!refreshToken.isNullOrEmpty()) {
                ILog.d(TAG, "Access Token 不存在，尝试使用 Refresh Token 刷新...")
                val newToken = refreshTokenIfNeeded()
                return !newToken.isNullOrEmpty()
            }
            return false
        }
        
        // 检查 Token 是否过期（使用 TokenStore 的内部方法）
        val expiresAt = TokenStore.getTokenExpiresAt(accessToken)
        if (expiresAt == null || expiresAt <= System.currentTimeMillis() / 1000) {
            val refreshToken = TokenStore.getRefreshToken()
            if (!refreshToken.isNullOrEmpty()) {
                ILog.d(TAG, "Access Token 已过期，尝试使用 Refresh Token 刷新...")
                val newToken = refreshTokenIfNeeded()
                
                // 检查新 Token 是否有效
                val newExpiresAt = TokenStore.getTokenExpiresAt(newToken)
                if (!newToken.isNullOrEmpty() && newExpiresAt != null && newExpiresAt > System.currentTimeMillis() / 1000) {
                    ILog.d(TAG, "Access Token 刷新成功，用户仍然处于登录状态")
                    return true
                } else {
                    ILog.w(TAG, "Access Token 刷新失败或新 Token 无效，用户需要重新登录")
                    return false
                }
            } else {
                ILog.w(TAG, "Access Token 已过期且没有 Refresh Token，用户需要重新登录")
                return false
            }
        }
        
        return true
    }
    
    /**
     * 获取当前 Access Token
     */
    fun getAccessToken(): String? {
        return TokenStore.getAccessToken()
    }
    
    /**
     * 获取当前 Refresh Token
     */
    fun getRefreshToken(): String? {
        return TokenStore.getRefreshToken()
    }
    
    /**
     * 登出
     */
    fun logout() {
        TokenStore.clearToken()
        ILog.d(TAG, "用户已登出")
    }
    
    /**
     * 重写 tag 属性（供 Network 模块使用）
     */
    override val tag: String
        get() = TAG
}
