import Foundation

// 添加登出通知
extension Notification.Name {
    static let userDidLogoutNotification = Notification.Name("UserDidLogoutNotification")
}

// 请求标识符
private struct RequestIdentifier {
    static var currentId: Int = 0
    static var lock = NSLock()
    
    static func next() -> Int {
        lock.lock()
        defer { lock.unlock() }
        currentId += 1
        return currentId
    }
}

enum NetworkError: Error {
    case invalidURL
    case noData
    case decodingError(Error)
    case serverError(String)
    case unauthorized
    case other(Error)
    case networkError(Error)
    case unknownError(Error)
    
    var localizedDescription: String {
        switch self {
        case .invalidURL:
            return "无效的URL"
        case .noData:
            return "没有收到数据"
        case .decodingError(let error):
            return "数据解析错误: \(error.localizedDescription)"
        case .serverError(let message):
            return "服务器错误: \(message)"
        case .unauthorized:
            return "未授权，请重新登录"
        case .other(let error):
            return error.localizedDescription
        case .networkError(let error):
            return "网络请求错误: \(error.localizedDescription)"
        case .unknownError(let error):
            return "未知错误: \(error.localizedDescription)"
        }
    }
}

class NetworkService {
    static let shared = NetworkService()
    
    // 默认请求头
    private let defaultHeaders: [String: String] = [
        "Content-Type": "application/json",
        "Accept": "application/json"
    ]
    
    private var isRefreshing = false
    private var requestsToRetry: [(URLRequest, (Result<Data, NetworkError>) -> Void, Int)] = []
    
    private init() {}
    
    // MARK: - 基础请求方法
    private func request<T: Decodable>(
        _ method: String,
        path: String,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (Result<T, NetworkError>) -> Void
    ) {
        // 生成请求ID
        let requestId = RequestIdentifier.next()
        
        // 构建URL
        let fullURL = APIConfig.baseURL + path
        guard let url = URL(string: fullURL) else {
            print("❌ [Network][#\(requestId)][\(method) \(path)] 无效的URL")
            completion(.failure(.invalidURL))
            return
        }
        
        // 创建请求
        var request = URLRequest(url: url)
        request.httpMethod = method
        
        // 设置请求头 - 合并默认头、认证头和自定义头
        defaultHeaders.forEach { key, value in
            request.setValue(value, forHTTPHeaderField: key)
        }
        
        // 添加认证头
        APIConfig.authHeaders.forEach { key, value in
            request.setValue(value, forHTTPHeaderField: key)
        }
        
        // 添加自定义头（如果提供）
        headers?.forEach { key, value in
            request.setValue(value, forHTTPHeaderField: key)
        }
        
        // 设置请求体（如果是POST/PUT请求）
        if let parameters = parameters, (method == "POST" || method == "PUT") {
            do {
                request.httpBody = try JSONSerialization.data(withJSONObject: parameters)
            } catch {
                print("❌ [Network][#\(requestId)][\(method) \(path)] 参数序列化失败: \(error.localizedDescription)")
                completion(.failure(.other(error)))
                return
            }
        }
        
        // 打印请求信息
        print("""
        🌐 [Network][#\(requestId)][\(method) \(path)] 开始请求
        🔗 URL: \(url.absoluteString)
        📤 Headers: \(request.allHTTPHeaderFields ?? [:])
        📦 Body: \(request.httpBody.flatMap { String(data: $0, encoding: .utf8) } ?? "")
        """)
        
        // 创建任务
        let startTime = Date()
        let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
            let duration = String(format: "%.3fs", Date().timeIntervalSince(startTime))
            
            // 处理响应
            self?.handleResponse(
                requestId: requestId,
                method: method,
                path: path,
                data: data,
                response: response,
                error: error,
                request: request,
                duration: duration,
                completion: { (result: Result<T, NetworkError>) in
                    completion(result)
                }
            )
        }
        
        // 开始请求
        task.resume()
    }
    
    private func handleResponse<T: Decodable>(
        requestId: Int,
        method: String,
        path: String,
        data: Data?,
        response: URLResponse?,
        error: Error?,
        request: URLRequest,
        duration: String,
        completion: @escaping (Result<T, NetworkError>) -> Void
    ) {
        // 打印响应信息
        if let httpResponse = response as? HTTPURLResponse {
            let statusCode = httpResponse.statusCode
            let statusMessage = HTTPURLResponse.localizedString(forStatusCode: statusCode)
            
            // 处理401未授权
            if statusCode == 401 {
                print("""
                🔑 [Network][#\(requestId)][\(method) \(path)] 检测到未授权，尝试刷新token...
                ⏱️ 耗时: \(duration)
                """)
                
                // 将请求加入重试队列
                let dataResult = data.flatMap { Result<Data, NetworkError>.success($0) } ?? .failure(.noData)
                self.requestsToRetry.append((request, { result in
                    switch result {
                    case .success(let data):
                        do {
                            let decoder = JSONDecoder()
                            let result = try decoder.decode(T.self, from: data)
                            print("""
                            ✅ [Network][#\(requestId)][\(method) \(path)] 重试成功
                            ⏱️ 总耗时: \(duration) (包含token刷新时间)
                            """)
                            completion(.success(result))
                        } catch let decodingError as DecodingError {
                            print("""
                            ❌ [Network][#\(requestId)][\(method) \(path)] JSON解析失败
                            🔍 错误: \(decodingError.localizedDescription)
                            📦 原始数据: \(String(data: data, encoding: .utf8) ?? "")
                            """)
                            completion(.failure(.decodingError(decodingError)))
                        } catch {
                            print("""
                            ❌ [Network][#\(requestId)][\(method) \(path)] 未知错误
                            🔍 错误: \(error.localizedDescription)
                            """)
                            completion(.failure(.unknownError(error)))
                        }
                    case .failure(let error):
                        print("""
                        ❌ [Network][#\(requestId)][\(method) \(path)] 重试失败
                        🔍 错误: \(error.localizedDescription)
                        """)
                        completion(.failure(error))
                    }
                }, requestId))
                
                // 如果没有正在刷新的请求，则开始刷新token
                if !isRefreshing {
                    refreshAndRetryRequests()
                }
                return
            }
            
            // 处理其他错误状态码
            if !(200...299).contains(statusCode) {
                let errorMessage = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
                print("""
                ❌ [Network][#\(requestId)][\(method) \(path)] 请求失败
                📊 状态码: \(statusCode) (\(statusMessage))
                ⏱️ 耗时: \(duration)
                🔍 错误响应: \(errorMessage)
                """)
                completion(.failure(.serverError("状态码: \(statusCode), 响应: \(errorMessage)")))
                return
            }
            
            // 成功响应
            print("""
            ✅ [Network][#\(requestId)][\(method) \(path)] 请求成功
            📊 状态码: \(statusCode) (\(statusMessage))
            ⏱️ 耗时: \(duration)
            """)
        }
        
        // 处理网络错误
        if let error = error {
            print("""
            ❌ [Network][#\(requestId)][\(method) \(path)] 网络请求失败
            ⏱️ 耗时: \(duration)
            🔍 错误: \(error.localizedDescription)
            """)
            completion(.failure(.networkError(error)))
            return
        }
        
        // 检查数据是否存在
        guard let data = data else {
            print("""
            ❌ [Network][#\(requestId)][\(method) \(path)] 没有收到数据
            ⏱️ 耗时: \(duration)
            """)
            completion(.failure(.noData))
            return
        }
        
        // 打印响应数据（调试用）
        if let responseString = String(data: data, encoding: .utf8) {
            print("""
            📥 [Network][#\(requestId)][\(method) \(path)] 响应数据:
            \(responseString.prefix(1000))\(responseString.count > 1000 ? "..." : "")
            """)
        }
        
        do {
            // 解析JSON数据
            let decoder = JSONDecoder()
            let result = try decoder.decode(T.self, from: data)
            completion(.success(result))
        } catch let decodingError as DecodingError {
            print("""
            ❌ [Network][#\(requestId)][\(method) \(path)] JSON解析失败
            🔍 错误: \(decodingError.localizedDescription)
            📦 原始数据: \(String(data: data, encoding: .utf8) ?? "")
            """)
            completion(.failure(.decodingError(decodingError)))
        } catch {
            print("""
            ❌ [Network][#\(requestId)][\(method) \(path)] 未知错误
            🔍 错误: \(error.localizedDescription)
            """)
            completion(.failure(.unknownError(error)))
        }
    }
    
    private func refreshAndRetryRequests() {
        guard !isRefreshing else { return }
        
        isRefreshing = true
        let refreshStartTime = Date()
        
        print("🔄 [Network] 开始刷新Token...")
        
        TokenManager.shared.refreshToken { [weak self] success, _ in
            guard let self = self else { return }
            
            let refreshDuration = String(format: "%.3fs", Date().timeIntervalSince(refreshStartTime))
            
            if success {
                print("""
                ✅ [Network] Token刷新成功
                ⏱️ 耗时: \(refreshDuration)
                🔄 准备重试\(self.requestsToRetry.count)个请求...
                """)
                
                // 重试所有待处理的请求
                let requestsToRetry = self.requestsToRetry
                self.requestsToRetry.removeAll()
                
                for (request, completion, requestId) in requestsToRetry {
                    var newRequest = request
                    if let token = KeychainHelper.getAccessToken() {
                        newRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
                    }
                    
                    let task = URLSession.shared.dataTask(with: newRequest) { data, response, error in
                        if let data = data {
                            completion(.success(data))
                        } else if let error = error {
                            completion(.failure(.networkError(error)))
                        } else {
                            completion(.failure(.noData))
                        }
                    }
                    task.resume()
                }
            } else {
                print("""
                ❌ [Network] Token刷新失败
                ⏱️ 耗时: \(refreshDuration)
                🚪 清除登录状态...
                """)
                
                // 清除token并通知需要重新登录
                TokenManager.shared.clearTokens()
                DispatchQueue.main.async {
                    NotificationCenter.default.post(name: .userDidLogoutNotification, object: nil)
                }
                
                // 所有待处理的请求都返回未授权错误
                self.requestsToRetry.forEach { _, completion, _ in
                    completion(.failure(.unauthorized))
                }
                self.requestsToRetry.removeAll()
            }
            
            self.isRefreshing = false
        }
    }
    
    // MARK: - 公共方法
    
    /// GET 请求
    func get<T: Decodable>(
        path: String,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (Result<T, NetworkError>) -> Void
    ) {
        request("GET", path: path, parameters: parameters, headers: headers, completion: completion)
    }
    
    /// POST 请求
    func post<T: Decodable>(
        path: String,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (Result<T, NetworkError>) -> Void
    ) {
        request("POST", path: path, parameters: parameters, headers: headers, completion: completion)
    }
    
    /// POST 请求（带Token）
    func postWithToken<T: Decodable>(
        path: String,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (Result<T, NetworkError>) -> Void
    ) {
        var headers = headers ?? [:]
        if let token = KeychainHelper.getAccessToken() {
            headers["Authorization"] = "Bearer \(token)"
        }
        post(path: path, parameters: parameters, headers: headers, completion: completion)
    }
    
    /// DELETE 请求
    func delete<T: Decodable>(
        path: String,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (Result<T, NetworkError>) -> Void
    ) {
        request("DELETE", path: path, parameters: parameters, headers: headers, completion: completion)
    }
    
    /// PUT 请求
    func put<T: Decodable>(
        path: String,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (Result<T, NetworkError>) -> Void
    ) {
        request("PUT", path: path, parameters: parameters, headers: headers, completion: completion)
    }
}
