// Copyright © 2025 VOID Software SA. All rights reserved. import Foundation /// Custom error types for API operations enum APIError: Error, LocalizedError, Equatable { case invalidURL case noData case decodingFailed(Error) case encodingFailed(Error) case unauthorized case forbidden case notFound case serverError(statusCode: Int) case networkError(Error) case unexpectedResponse case timeout case cancelled case custom(String) var errorDescription: String? { switch self { case .invalidURL: return "Invalid URL" case .noData: return "No data received from server" case .decodingFailed(let error): return "Failed to decode response: \(error.localizedDescription)" case .encodingFailed(let error): return "Failed to encode parameters: \(error.localizedDescription)" case .unauthorized: return "Unauthorized. Please login again." case .forbidden: return "Access forbidden" case .notFound: return "Resource not found" case .serverError(let statusCode): return "Server error (Status: \(statusCode))" case .networkError(let error): return "Network error: \(error.localizedDescription)" case .unexpectedResponse: return "Unexpected response from server" case .timeout: return "Request timeout" case .cancelled: return "Request cancelled" case .custom(let message): return message } } static func == (lhs: APIError, rhs: APIError) -> Bool { switch (lhs, rhs) { case (.invalidURL, .invalidURL), (.noData, .noData), (.unauthorized, .unauthorized), (.forbidden, .forbidden), (.notFound, .notFound), (.unexpectedResponse, .unexpectedResponse), (.timeout, .timeout), (.cancelled, .cancelled): return true case (.serverError(let lhsCode), .serverError(let rhsCode)): return lhsCode == rhsCode case (.custom(let lhsMessage), .custom(let rhsMessage)): return lhsMessage == rhsMessage case (.decodingFailed(let lhsError), .decodingFailed(let rhsError)): return lhsError.localizedDescription == rhsError.localizedDescription case (.encodingFailed(let lhsError), .encodingFailed(let rhsError)): return lhsError.localizedDescription == rhsError.localizedDescription case (.networkError(let lhsError), .networkError(let rhsError)): return lhsError.localizedDescription == rhsError.localizedDescription default: return false } } } /// Detailed server error with request/response information struct ServerError: Error, LocalizedError { let statusCode: Int? let message: String? let data: Data? let request: URLRequest? let response: HTTPURLResponse? var errorDescription: String? { if let message = message { return message } if let statusCode = statusCode { return "Server error: \(statusCode)" } return "Unknown server error" } init( statusCode: Int? = nil, message: String? = nil, data: Data? = nil, request: URLRequest? = nil, response: HTTPURLResponse? = nil ) { self.statusCode = statusCode self.message = message self.data = data self.request = request self.response = response } }