//
//  LNHttpManager.swift
//  Lanu
//
//  Created by OneeChan on 2025/11/6.
//

import Foundation

/// HTTP请求方法枚举
enum HTTPMethod: String {
    case get = "GET"
    case post = "POST"
    case put = "PUT"
    case delete = "DELETE"
}

/// HTTP请求错误枚举
enum LNHttpError: Error, LocalizedError {
    case invalidURL
    case invalidResponse
    case networkError(Error)
    case parsingError(Error)
    case statusCode(Int)
    case serverError(Int, String)
    
    var errorDesc: String {
        switch self {
        case .invalidURL: "无效的URL"
        case .invalidResponse: "无效的响应"
        case .networkError(let error): error.localizedDescription
        case .parsingError(let error): error.localizedDescription
        case .statusCode(let code): .init(key: "B00125", code)
        case .serverError(_, let error): error
        }
    }
}

enum LNHttpCommonErrorCode: Int {
    case beKicked = 100004
}

/// HTTP请求管理器
class LNHttpManager {
    static let shared = LNHttpManager()
    private let session: URLSession
    
    private init() {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30
        configuration.timeoutIntervalForResource = 60
        session = URLSession(configuration: configuration)
    }
    
    /// 通用HTTP请求方法
    /// - Parameters:
    ///   - urlString: 请求URL字符串
    ///   - method: HTTP方法
    ///   - parameters: 请求参数
    ///   - headers: 请求头
    ///   - completion: 完成回调
    func request<T: Decodable>(
        path: String,
        method: HTTPMethod = .get,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (T?, LNHttpError?) -> Void
    ) {
        var sign = ""
        var commonHeader: [String: String] = [:]
        
        let id = "\(Int(curTimeInNano))"
        sign += id
        commonHeader["id"] = id
        
        let udid = curDeviceId
        sign += udid
        commonHeader["udid"] = udid
        
        let app = curAppBundleIdentifier
        sign += app
        commonHeader["app"] = app
        
        let device = curDeviceModelName
        sign += device
        commonHeader["device"] = device
        
        let platform = "2"
        sign += platform
        commonHeader["platform"] = platform
        
        let channel = "appStore"
        sign += channel
        commonHeader["channel"] = channel
        
        let api = "1"
        sign += api
        commonHeader["api"] = api
        
        let version = curBuildVersion
        sign += version
        commonHeader["version"] = version
        
        let network = LNNetworkMonitor.curNetworkType.desc
        sign += network
        commonHeader["network"] = network
        
        let time = "\(Int(curTimeInMicro))"
        sign += time
        commonHeader["time"] = time
        
        let token = LNAccountManager.shared.token
        if !token.isEmpty {
            sign += token
            commonHeader["token"] = token
        }
        
        let secret = "abc|abc|edg|9527|1234"
        sign += secret
        
        let mergedHeader = commonHeader.merging(headers ?? [:]) { $1 }
        
        // 检查URL是否有效
        guard let url = buildURL(from: path, method: method, parameters: parameters) else {
            completion(nil, .invalidURL)
            return
        }
        
        // 创建请求
        var request = URLRequest(url: url)
        request.httpMethod = method.rawValue
        
        // 设置请求头
        mergedHeader.forEach { key, value in
            request.addValue(value, forHTTPHeaderField: key)
        }
        request.addValue(LNAppConfig.shared.curLang.bundleName, forHTTPHeaderField: "Accept-Language")
        
        // 设置请求体（POST, PUT等方法）
        if method != .get, let parameters = parameters {
            let body = try? JSONSerialization
                .data(withJSONObject: parameters)
            request.httpBody = body
            if let body, let bodyStr = String(data: body, encoding: .utf8) {
                sign += bodyStr
            }
        }
        request.addValue(sign.md5, forHTTPHeaderField: "sign")
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        
        // 执行请求
        let task = session.dataTask(with: request) {
            [weak self] data,
            response,
            error in
            guard let self else { return }
            
            // 处理网络错误
            if let error = error {
                Log.d("receive \(request.url?.absoluteString ?? "") error: \(error.localizedDescription)")
                completion(nil, .networkError(error))
                return
            }
            
            // 检查响应是否有效
            guard let httpResponse = response as? HTTPURLResponse else {
                Log.d("receive \(request.url?.absoluteString ?? "") response error")
                
                completion(nil, .invalidResponse)
                return
            }
            
            if let data {
                Log.d("receive \(request.url?.absoluteString ?? "") code:\(httpResponse.statusCode) data \(String(data: data, encoding: .utf8) ?? "")")
            } else {
                Log.d("receive \(request.url?.absoluteString ?? "") code:\(httpResponse.statusCode)")
            }
            
            // 检查状态码
            guard 200...299 ~= httpResponse.statusCode else {
                completion(nil, .statusCode(httpResponse.statusCode))
                return
            }
            
            // 处理响应数据
            guard let data = data else {
                completion(nil, .invalidResponse)
                return
            }
            
            // 解析JSON数据
            self.parseJSON(data: data, completion: completion)
        }
        
        if let body = request.httpBody {
            Log.d("send \(request.httpMethod ?? "") - \(request.url?.absoluteString ?? "") \(String(data: body, encoding: .utf8) ?? "")")
        } else {
            Log.d("send \(request.httpMethod ?? "") - \(request.url?.absoluteString ?? "")")
        }
        task.resume()
    }
    
    /// 构建请求URL（处理GET参数）
    private func buildURL(from path: String, method: HTTPMethod, parameters: [String: Any]?) -> URL? {
        guard var urlComponents = URLComponents(string: LNNetworkConfig.host + (path.starts(with: "/") ? path : "/\(path)")) else {
            return nil
        }
        
        // GET方法的参数拼接到URL上
        if method == .get, let parameters = parameters {
            urlComponents.queryItems = parameters.map { key, value in
                URLQueryItem(name: key, value: "\(value)")
            }
        }
        
        return urlComponents.url
    }
    
    /// 解析JSON数据
    private func parseJSON<T: Decodable>(
        data: Data,
        completion: @escaping (T?, LNHttpError?) -> Void
    ) {
        do {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .useDefaultKeys // 处理蛇形命名
            let result = try decoder.decode(LNHttpResponse<T>.self, from: data)
            if result.code != 0 {
                if result.code == LNHttpCommonErrorCode.beKicked.rawValue {
                    LNAccountManager.shared.clean()
                }
                completion(nil, .serverError(result.code, result.msg))
            } else {
                completion(result.data, nil)
            }
        } catch {
            completion(nil, .parsingError(error))
        }
    }
}

// MARK: - 便捷请求方法扩展
extension LNHttpManager {
    /// 发送GET请求
    func get<T: Decodable>(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (T?, LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .get,
            parameters: params,
            completion: completion
        )
    }
    
    /// 发送POST请求
    func post<T: Decodable>(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (T?, LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .post,
            parameters: params,
            completion: completion
        )
    }
    
    /// 发送PUT请求
    func put<T: Decodable>(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (T?, LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .put,
            parameters: params,
            completion: completion
        )
    }
    
    /// 发送DELETE请求
    func delete<T: Decodable>(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (T?, LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .delete,
            parameters: params,
            completion: completion
        )
    }
}

extension LNHttpManager {
    func request(
        path: String,
        method: HTTPMethod = .get,
        parameters: [String: Any]? = nil,
        headers: [String: String]? = nil,
        completion: @escaping (LNHttpError?) -> Void
    ) {
        let handler: (
            LNHttpEmptyResponse?, LNHttpError?
        ) -> Void = { _, err in
            completion(err)
        }
        request(
            path: path,
            method: method,
            parameters: parameters,
            headers: headers,
            completion: handler
        )
    }
    /// 发送GET请求
    func get(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .get,
            parameters: params,
            completion: completion
        )
    }
    
    /// 发送POST请求
    func post(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .post,
            parameters: params,
            completion: completion
        )
    }
    
    /// 发送PUT请求
    func put(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .put,
            parameters: params,
            completion: completion
        )
    }
    
    /// 发送DELETE请求
    func delete(
        path: String,
        params: [String: Any]? = nil,
        completion: @escaping (LNHttpError?) -> Void
    ) {
        request(
            path: path,
            method: .delete,
            parameters: params,
            completion: completion
        )
    }
}
