//
//  LocationsClient.swift
//  Locations
//
//  Created by Javier Cicchelli on 10/04/2023.
//  Copyright © 2023 Röck+Cöde. All rights reserved.
//

import APICore
import Foundation

struct LocationsClient {
    
    // MARK: Properties
    
    private let session: URLSession
    private let decoder: JSONDecoder = .init()
    private let makeURLRequest: MakeURLRequestUseCase = .init()
    
    // MARK: Initialisers

    init(configuration: URLSessionConfiguration = .default) {
        self.session = .init(configuration: configuration)
    }

}

// MARK: - Client

extension LocationsClient: Client {
    
    // MARK: Functions
    
    func request<Model: Decodable>(
        endpoint: some Endpoint,
        for model: Model.Type
    ) async throws -> Model {
        let urlRequest = try makeURLRequest(endpoint: endpoint)
        let (data, response) = try await session.data(for: urlRequest)
        
        guard let httpResponse = response as? HTTPURLResponse else {
            throw LocationsClientError.responseNotReturned
        }
        
        switch httpResponse.statusCode {
        case 200:
            return try decoder.decode(model, from: data)
        case 400...499:
            throw LocationsClientError.statusErrorClient
        case 500...599:
            throw LocationsClientError.statusErrorServer
        default:
            throw LocationsClientError.statusErrorUnexpected
        }
    }

}

// MARK: - Errors

public enum LocationsClientError: Error {
    case responseNotReturned
    case statusErrorClient
    case statusErrorServer
    case statusErrorUnexpected
}
