//
//  SDLApi.swift
//  sdlan
//
//  Created by 安礼成 on 2024/6/5.
//

import Foundation

struct SDLAPIResponse<T: Decodable>: Decodable {
    let code: Int
    let message: String?
    let data: T?
}

struct SDLAPIError: Error, Decodable {
    let code: Int
    let message: String
}

struct SDLAPIClient {
    
    static var baseUrl: String {
        return "https://\(SystemConfig.serverHost)/api"
    }
    
    static private let token: String = "H6p*2RfEu4ITcL"
    
    // 基础参数信息
    static let baseParams: [String: Any] = [
        "client_id": SystemConfig.getClientId(),
        "mac": SystemConfig.macAddressString(mac: SystemConfig.getMacAddress())
    ]
    
    static func doPost<T: Decodable>(path: String, params: [String: Any], as: T.Type) async throws -> T {
        let config = URLSessionConfiguration.ephemeral
        config.connectionProxyDictionary = [:]
        let session = URLSession(configuration: config)
        
        let postData = try! JSONSerialization.data(withJSONObject: params)
        let url = URL(string: baseUrl + path)!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue(sign(params: params), forHTTPHeaderField: "X-sign")
        request.httpBody = postData
        
        let (data, _) = try await session.data(for: request)
        if let response = String(bytes: data, encoding: .utf8) {
            NSLog("url: \(path), response is: \(response)")
        }
        
        let apiResponse = try JSONDecoder().decode(SDLAPIResponse<T>.self, from: data)
        // code = 0 表示成功
        if apiResponse.code == 0 {
            if let data = apiResponse.data {
                return data
            } else if let data = apiResponse.message as? T {
                return data
            } else {
                throw SDLAPIError(code: 0, message: "数据格式错误")
            }
        } else if let message = apiResponse.message {
            throw SDLAPIError(code: apiResponse.code, message: message)
        } else {
            throw DecodingError.dataCorrupted(
                .init(
                    codingPath: [],
                    debugDescription: "Invalid JSON-RPC response: \(String(data: data, encoding: .utf8) ?? "")"
                )
            )
        }
    }
    
    private static func sign(params: [String: Any]) -> String {
        let keys = params.keys.sorted()
        
        let qs = keys.map { key in
            let str = String(describing: params[key] ?? "")
            return "\(key)=\(str)"
        }.joined(separator: "&")
        
        return SDLUtil.hmacMD5(key: token, data: qs)
    }
    
}
