//
//  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" // 按需修改
        ]
    }
    
    lazy var afSession: Session = {
//        let configuration = URLSessionConfiguration.af.default
//        configuration.timeoutIntervalForRequest = 30  // 请求超时时间（秒）
//        configuration.timeoutIntervalForResource = 30 // 资源超时时间（秒）
//        let session = Session(configuration: configuration)
//        return session
        return AF
    }()
    lazy var encoder: JSONEncoding = {
        return JSONEncoding(options: .withoutEscapingSlashes)// 关键：禁用斜杠转义
    }()

    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: [.withoutEscapingSlashes])//去掉转义
            urlRequest.httpBody = jsonData
        } catch {
            dePrint("Failed to encode parameters: \(error)")
            completion(.failure(error))
            return nil
        }
        
        // 3. 使用 streamRequest 发起流式请求
        let request = afSession.streamRequest(urlRequest)
        request.responseStreamString{ stream in
            switch stream.event {
            case .stream(let result):
                switch result {
                case .success(let string):
                    dePrint("🚰🚰🚰Stream Received string 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,
        completion: @escaping (Result<Any, Error>) -> Void
    ) -> Request{
        dePrint("✈️✈️✈️网络请求:\(urlString)")
        dePrint("✈️✈️✈️参数:\(String(describing: parameters))")
        
        var encoding: ParameterEncoding = URLEncoding.default
        if method == .post {
            encoding = encoder
        }
        let request = afSession.request(urlString, method: method, parameters: parameters, encoding: encoding, headers: defaultHeaders, interceptor: nil)
        request.responseString { response in
                self.handleResponse(response, completion: completion)
            }
        return request
    }
    
    

    
}

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 = afSession.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)%")
                progressHandler(progress)
            }
            .responseString{ response in
                // 4. 处理响应
                self.handleResponse(response, completion: completion)
        }
        
        return request
    }
    
    
    /// 下载文件
    /// - Parameters:
    ///   - url: 下载URL
    ///   - destination: 目标保存路径 (可选，不传则使用临时目录)
    ///   - progressHandler: 进度回调 (0.0~1.0)
    ///   - completion: 完成回调 (返回文件URL或错误)
    func downloadFile(
        urlString: String,
        to destination: URL? = nil,
        progressHandler: ((Double) -> Void)? = nil,
        completion: @escaping (Result<URL, Error>) -> Void
    ) -> DownloadRequest? {
        
        
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "url nil", code: 0)))
            return nil
        }
        
        // 设置下载目标路径
        let destination: DownloadRequest.Destination = { temporaryURL, response in
            // 如果用户指定了目标路径
            if let destination = destination {
                // 确保目录存在
                let directory = destination.deletingLastPathComponent()
                try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
                return (destination, [.removePreviousFile, .createIntermediateDirectories])
            }
            
            // 否则使用临时目录
            let documentsURL = FileManager.default.temporaryDirectory
            let suggestedFilename = response.suggestedFilename ?? url.lastPathComponent
            let fileURL = documentsURL.appendingPathComponent(suggestedFilename)
            
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }
        
        // 开始下载
        let request = afSession.download(url, to: destination)
            .downloadProgress { progress in
                // 主线程回调进度
                DispatchQueue.main.async {
                    progressHandler?(progress.fractionCompleted)
                }
            }
            .response { response in
                // 主线程回调结果
                DispatchQueue.main.async {
                    switch response.result {
                    case .success(let fileURL):
                        if let fileURL = fileURL {
                            completion(.success(fileURL))
                        } else {
                            completion(.failure(NSError(domain: "DownloadError", code: -1, userInfo: [NSLocalizedDescriptionKey: "文件路径无效"])))
                        }
                    case .failure(let error):
                        completion(.failure(error))
                    }
                }
            }
        
        return request
    }

}

extension TSNetworkManager {
    
    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<String>,
                       completion: @escaping (Result<Any, Error>) -> Void){
        dePrint("🚗🚗🚗网络请求成功:\(String(describing: response.request?.url?.absoluteString))")
        dePrint("🚗🚗🚗网络请求成功:\(response)")
        completion(.success(data))
       }
    
    func handleFail(error:Error,
                    response: AFDataResponse<String>,
                    completion: @escaping (Result<Any, Error>) -> Void){
        dePrint("🚗🚗🚗网络请求失败:\(String(describing: response.request?.url?.absoluteString))")
        dePrint("🚗🚗🚗网络请求失败:\(response)")
        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 kNetWorkCodeSuccess(data:Any?) -> [String:Any]? {
    guard let data = data else { return nil }
    if let dataDict = data as? [String:Any]{
        let code = dataDict.safeInt(forKey: "code")
        
        switch code {
        case 200://成功
            return dataDict
//        case 400://机器人提示
//            TSAbnormalPopUpAlertVC.showRobotWarning()
//            return nil
        default:
            return nil
        }
    }
    return nil
}



func kNetWorkResultSuccess(data:Any?) -> [String:Any]? {
    guard let dataDict = kNetWorkCodeSuccess(data: data) else { return nil }
    if 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]
    }
}

extension TSNetworkManager {

    /// 发送 POST 请求
    /// - Parameters:
    ///   - urlString: 请求的 URL 字符串
    ///   - parameters: 请求的参数字典（将自动转换为 JSON）
    ///   - timeout: 超时时间（默认 30 秒）
    ///   - completion: 请求完成的回调，返回 `Data?` 和 `Error?`
    static func postRequest(
        urlString: String,
        httpBody: Data?,
        timeout: TimeInterval = 90,
        completion: @escaping (Data?, Error?) -> Void
    ) {
        // 确保 URL 有效
        guard let url = URL(string: urlString) else {
            completion(nil, NSError(domain: "Invalid URL", code: -1, userInfo: nil))
            return
        }
        debugPrint("postRequest urlString=",urlString)
        // 创建请求
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.timeoutInterval = timeout
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = httpBody
  
        // 创建数据任务
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            completion(data, error)
        }
        
        // 启动任务
        task.resume()
    }
}
