//
//  NetworkManager.swift
//  AIEmoji
//
//  Created by 100Years on 2025/1/16.
//

import Alamofire
import ObjectMapper


let TSNetworkShared = TSNetworkManager.shared

/// 网络工具类
class TSNetworkManager {
    
    static let shared = TSNetworkManager()
    private init() {}
    
    /// 通用 Headers
    private var defaultHeaders: HTTPHeaders {
        return ["Content-Type": "application/json",
                "accept": "application/json",
//            "Authorization": "Bearer YOUR_ACCESS_TOKEN" // 按需修改
        ]
    }
    
    private let urlCache = URLCache.shared
    
    func postStreamRequest(
        urlString: String,
        parameters: [String: Any]? = nil,
        streamHandler:@escaping (String) -> Void,
        completion: @escaping (Result<Any, Error>) -> Void
    )-> Request? {
        
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "url nil", code: 0)))
            return nil
        }
        
        // 1. 创建 URLRequest
        var urlRequest = URLRequest(url:URL(string: urlString)!)
        urlRequest.httpMethod = "POST"
        urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        // 2. 将字典参数转换为 JSON 数据并设置为请求体
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [])
            urlRequest.httpBody = jsonData
        } catch {
            dePrint("Failed to encode parameters: \(error)")
            completion(.failure(error))
            return nil
        }
        
        // 3. 使用 AF.streamRequest 发起流式请求
        let request = AF.streamRequest(urlRequest)
        request.responseStreamString{ stream in
            DispatchQueue.main.async {
                switch stream.event {
                case .stream(let result):
                    switch result {
                    case .success(let string):
                        dePrint("Stream Received string: \(string)")
                        streamHandler(string)
                    case .failure(let error):
                        dePrint("Stream error: \(error)")
                        completion(.failure(error))
                    }
                case .complete(let cpl):
                    if let error = cpl.error {
                        dePrint("Stream Request failed with error: \(error)")
                        completion(.failure(error))
                    } else {
                        dePrint("Stream success")
                        completion(.success("Stream success"))
                    }
                }
            }
        }
        return request
    }

    func request(
        method:HTTPMethod,
        urlString: String,
        parameters: [String: any Any & Sendable]? = nil,
        useCache: Bool = false,
        completion: @escaping (Result<Any, Error>) -> Void
    ) -> Request?{
        dePrint("✈️✈️✈️网络请求:\(urlString)")
        dePrint("✈️✈️✈️参数:\(String(describing: parameters))")
        
        var urlRequest:URLRequest?
        if method == .post {
            urlRequest = postRequest(url: urlString, parameters: parameters)
        }else if method == .get {
            urlRequest = getRequest(url: urlString, parameters: parameters)
        }
        
        guard var urlRequest = urlRequest else {
            completion(.failure(NSError(domain: "url nil", code: 0)))
            return nil
        }
        
        //设置缓存策略
        if useCache {
            urlRequest.cachePolicy = .returnCacheDataElseLoad // 优先使用缓存
        }else{
            urlRequest.cachePolicy = .reloadIgnoringLocalCacheData // 忽略缓存
        }
        
        //检查缓存
        if useCache, let cachedResponse = urlCache.cachedResponse(for: urlRequest) {
            handleCached(responseData: cachedResponse.data, urlString: urlString, completion: completion)
            return nil
        }
        
        let request = AF.request(urlRequest)
        request.validate().responseData { response in
            
            switch response.result {
            case .success(let value):
                // 缓存响应数据
                if useCache, let httpResponse = response.response {
                    let cachedResponse = CachedURLResponse(response: httpResponse, data: value)
                    self.urlCache.storeCachedResponse(cachedResponse, for: urlRequest)
                    dePrint("📥📥📥存入网络缓存:\(urlString)")
                }
            case .failure(_):
                break
            }
            
            self.handleResponse(response, completion: completion)
        }
        
        return request
    }
    
}


extension TSNetworkManager {
    
    func getRequest(url: String,parameters: [String: Any]? = nil) -> URLRequest? {
        // 构建 URL
        var components = URLComponents(string: url)
        
        if let parameters = parameters {
            let sortedParameters = parameters.sorted { $0.key < $1.key } // 1. 对字典的键值对按键名进行排序
            components?.queryItems = sortedParameters.map { URLQueryItem(name: $0.key, value: "\($0.value)") }
        }
        
        guard let url = components?.url else {
            return nil
        }
        
        // 创建 URLRequest
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        return request
    }
    
    // MARK: - POST 请求
    func postRequest(url: String,parameters: [String: Any]? = nil) -> URLRequest? {
        // 构建 URL
        guard let url = URL(string: url) else {
            return nil
        }
        
        var httpBody:Data?
        // 设置请求体
        if let parameters = parameters {
            do {
                httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
            } catch {
                return nil
            }
        }
        
        // 创建 URLRequest
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = httpBody
        return request
    }
    
    
    /// 清除特定 URL 的缓存
    func removeCache(urlString: String) {
         guard let url = URL(string: urlString) else { return }
         let request = URLRequest(url: url)
         urlCache.removeCachedResponse(for: request)
         print("Cache cleared for URL: \(url)")
     }

     /// 清除全部缓存
     func clearAllCache() {
         urlCache.removeAllCachedResponses()
         print("All cache cleared")
     }
    
}
extension TSNetworkManager {
    
    
    /*
     // Data 数组
     let dataArray: [[String: Any]] = [
         [
             "data": imageData,
             "fieldName": "file1", // 字段名
             "fileName": "App-Icon.png", // 文件名
             "mimeType": "image/png" // MIME 类型
         ],
         [
             "data": textData,
             "fieldName": "file2", // 字段名
             "fileName": "hello.txt", // 文件名
             "mimeType": "text/plain" // MIME 类型
         ]
     ]
     */
    
    /// 上传多个 Data 数据
    /// - Parameters:
    ///   - url: 上传地址
    ///   - dataArray: Data 数组，每个元素是一个字典，包含 Data 和字段名
    ///   - parameters: 其他参数（可选）
    ///   - headers: 自定义请求头（可选）
    ///   - completion: 完成回调，返回结果或错误
    func uploadData(
        urlString: String,
        dataArray: [[String: Any]], // Data 数组，每个元素包含 Data 和字段名
        parameters: [String: Any]? = nil, // 其他参数
        headers: HTTPHeaders? = nil, // 自定义请求头
        progressHandler: @escaping (Progress) -> Void, // 上传进度回调
        completion: @escaping (Result<Any, Error>) -> Void
    )-> Request? {
        
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "url nil", code: 0)))
            return nil
        }
        
        // 1. 设置默认请求头
        var defaultHeaders: HTTPHeaders = [
            "accept": "application/json",
            "Content-Type": "multipart/form-data"
        ]
        // 合并自定义请求头
        if let customHeaders = headers {
            customHeaders.forEach { defaultHeaders[$0.name] = $0.value }
        }
        
        dePrint("✈️✈️✈️网络请求:\(urlString)")
        dePrint("✈️✈️✈️dataArray:\(String(describing: dataArray))")
        dePrint("✈️✈️✈️参数:\(String(describing: parameters))")
        // 2. 使用 Alamofire 上传 Data
        let request = AF.upload(
            multipartFormData: { multipartFormData in
                // 添加 Data
                for dataItem in dataArray {
                    if let data = dataItem["data"] as? Data,
                       let fieldName = dataItem["fieldName"] as? String,
                       let fileName = dataItem["fileName"] as? String,
                       let mimeType = dataItem["mimeType"] as? String {
                        multipartFormData.append(
                            data,
                            withName: fieldName,
                            fileName: fileName,
                            mimeType: mimeType
                        )
                    }
                }

                // 添加其他参数
                if let parameters = parameters {
                    for (key, value) in parameters {
                        if let data = "\(value)".data(using: .utf8) {
                            multipartFormData.append(data, withName: key)
                        }
                    }
                }
            },
            to: url, // 上传地址
            headers: defaultHeaders // 请求头
        )
        
        request
            .uploadProgress{ progress in
                // 3. 上传进度回调
                // 上传进度回调
                dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
                DispatchQueue.main.async {
                    progressHandler(progress)
                }
            }
            
            .responseData{ response in
                // 4. 处理响应
                self.handleResponse(response, completion: completion)
        }
        
        return request
    }

}

extension TSNetworkManager {
    
    
    private func handleResponse(
        _ response: AFDataResponse<Data>,
        completion: @escaping (Result<Any, Error>) -> Void
    ) {
        switch response.result {
        case .success(let data):
            if let resultDict = dataToJSONObject(data:data) as? [String:Any] {
                handleSuccess(data: resultDict, response: response, completion: completion)
            }else{
                handleFail(error: NSError(domain: "Unable to parse data", code: 0), response: response, completion: completion)
            }
        case .failure(let error):
            handleFail(error: error, response: response, completion: completion)
        }
    }
    
    
//    private func handleResponse(
//        _ response: AFDataResponse<String>,
//        completion: @escaping (Result<Any, Error>) -> Void
//    ) {
//        
//        switch response.result {
//        case .success(let value):
//
//            if let resultDict = dataToJSONObject(data:response.data) as? [String:Any] {
//                
////                let code = resultDict.safeInt(forKey: "code")
////                if responseType != nil {
////                    if let model = T(JSONString: value) {
////                        handleSuccess(data: model, response: response, completion: completion)
////                    } else {
////                        let models = Mapper<T>().mapArray(JSONString: value)
////                        handleSuccess(data: models ?? [], response: response, completion: completion)
////                    }
////                } else {
//                    handleSuccess(data: resultDict, response: response, completion: completion)
////                }
//                
//            }else{
//                handleFail(error: NSError(domain: "Unable to parse data", code: 0), response: response, completion: completion)
//            }
//
//        case .failure(let error):
//            handleFail(error: error, response: response, completion: completion)
//        }
//    }
    
    func handleSuccess(data:Any,
                       response: AFDataResponse<Data>,
                       completion: @escaping (Result<Any, Error>) -> Void){
        dePrint("🚗🚗🚗网络请求成功:\(String(describing: response.request?.url?.absoluteString))")
        dePrint("🚗🚗🚗网络请求成功:\(data)")
        DispatchQueue.main.async {
            completion(.success(data))
        }
       }
    
    func handleFail(error:Error,
                    response: AFDataResponse<Data>,
                    completion: @escaping (Result<Any, Error>) -> Void){
        dePrint("🚗🚗🚗网络请求失败:\(String(describing: response.request?.url?.absoluteString))")
        dePrint("🚗🚗🚗网络请求失败:\(error)")
        DispatchQueue.main.async {
            completion(.failure(error))
        }
    }
    
    func handleCached(responseData:Data,
                        urlString:String,
                       completion: @escaping (Result<Any, Error>) -> Void){
        dePrint("📤📤📤取出网络缓存:\(urlString)")
        if let resultDict = dataToJSONObject(data:responseData) as? [String:Any] {
            dePrint("📤📤📤网络请求成功:\(String(describing: urlString))")
            dePrint("📤📤📤网络请求成功:\(resultDict)")
            DispatchQueue.main.async {
                completion(.success(resultDict))
            }
        }else{
            
            dePrint("📤📤📤网络请求失败:\(String(describing: urlString))")
            dePrint("📤📤📤网络请求失败:Unable to parse data")
            let error = NSError(domain: "Unable to parse data", code: 0)
            DispatchQueue.main.async {
                completion(.failure(error))
            }
        }
    }
    
    func dataToJSONObject(data: Data?) -> Any? {
        guard let data = data else { return nil }
        do {
            let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
            return jsonObject
        } catch {
            print("Failed to convert Data to JSON object: \(error.localizedDescription)")
            return nil
        }
    }
    
}





func kNetWorkResultSuccess(data:Any?) -> [String:Any]? {
    guard let data = data else { return nil }
    if let dataDict = data as? [String:Any] ,
       dataDict.safeInt(forKey: "code") == 200,
       let result = dataDict["result"] as? [String:Any]{
        return result
    }
    return nil
}

func kNetWorkResultArraySuccess(data:Any?) -> [[String:Any]]? {
    guard let data = data else { return nil }
    if let dataDict = data as? [String:Any] ,
       dataDict.safeInt(forKey: "code") == 200,
       let result = dataDict["result"] as? [[String:Any]]{
        return result
    }
    return nil
}

func kNetWorkMessage(data:Any?) -> String? {
    guard let data = data else { return nil }
    if let dataDict = data as? [String:Any] ,
       let message = dataDict["message"] as? String{
        return message
    }
    return nil
}

  

class JsonStringTransform<T:Mappable>: TransformType {
    typealias Object = T
    typealias JSON = [String: Any]
    
    func transformFromJSON(_ value: Any?) -> T? {
    
        if let jsonString = value as? String {
            let obj = T(JSONString: jsonString)
            return obj
        }
        
        if let dict = value as? [String: Any] {
            let obj = T(JSON: dict)
            return obj
        }

        return nil
    }
    
    func transformToJSON(_ value: T?) -> [String : Any]? {
        return value?.toJSON() as? [String: Any]
    }
}
