import Foundation public enum UpstreamRoute: Hashable, Sendable { case health case device case sim case network case signalStrength case stats case statsCpu case connectivity case smsList(limit: Int, offset: Int, direction: String?) case smsSend(phoneNumber: String, content: String) case smsBatchDelete(ids: [Int]) case notificationConfig case notificationLogs(limit: Int, offset: Int) case notificationQueue(limit: Int) case notificationRetryAllQueue case notificationRetryQueue(id: String) case notificationDeleteQueue(id: String) case authLogin(password: String) case authLogout public var method: String { switch self { case .health, .device, .sim, .network, .signalStrength, .stats, .statsCpu, .connectivity, .smsList, .notificationConfig, .notificationLogs, .notificationQueue: return "GET" case .smsSend, .smsBatchDelete, .notificationRetryAllQueue, .notificationRetryQueue, .authLogin, .authLogout: return "POST" case .notificationDeleteQueue: return "DELETE" } } public var path: String { switch self { case .health: return "/api/health" case .device: return "/api/device" case .sim: return "/api/sim" case .network: return "/api/network" case .signalStrength: return "/api/network/signal-strength" case .stats: return "/api/stats" case .statsCpu: return "/api/stats/cpu" case .connectivity: return "/api/connectivity" case .smsList(let limit, let offset, let direction): var items = ["limit=\(limit)", "offset=\(offset)"] if let direction { items.append("direction=\(direction)") } return "/api/sms/list?\(items.joined(separator: "&"))" case .smsSend: return "/api/sms/send" case .smsBatchDelete: return "/api/sms/batch-delete" case .notificationConfig: return "/api/notifications/config" case .notificationLogs(let limit, let offset): return "/api/notifications/logs?limit=\(limit)&offset=\(offset)" case .notificationQueue(let limit): return "/api/notifications/queue?limit=\(limit)" case .notificationRetryAllQueue: return "/api/notifications/queue/retry-all" case .notificationRetryQueue(let id): return "/api/notifications/queue/\(id)/retry" case .notificationDeleteQueue(let id): return "/api/notifications/queue/\(id)" case .authLogin: return "/api/auth/login" case .authLogout: return "/api/auth/logout" } } public var body: Data? { switch self { case .smsSend(let phoneNumber, let content): return try? JSONSerialization.data( withJSONObject: ["phone_number": phoneNumber, "content": content] ) case .smsBatchDelete(let ids): return try? JSONSerialization.data(withJSONObject: ["ids": ids]) case .authLogin(let password): return try? JSONSerialization.data(withJSONObject: ["password": password]) default: return nil } } } public enum UpstreamError: Error, Equatable { case invalidRequest case unauthorized case forbidden case notSupported case timeout case transportFailed case invalidResponse }