//
//  CovidNetworking.swift
//  CovidSafe
//
//  Copyright © 2020 Australian Government. All rights reserved.
//

import Foundation
import Alamofire
import KeychainSwift

final class CovidServerTrustManager: ServerTrustManager {
    override func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {
        guard let evaluator = evaluators[host] else {
            for key in evaluators.keys {
                if (host.hasSuffix(key)) {
                    return evaluators[key]
                }
            }
            if allHostsMustBeEvaluated {
                throw AFError.serverTrustEvaluationFailed(reason: .noRequiredEvaluator(host: host))
            }

            return nil
        }
        return evaluator
    }
}

class CovidNetworking {
    static private let validCerts = [CovidCertificates.AmazonRootCA1, CovidCertificates.AmazonRootCA2, CovidCertificates.AmazonRootCA3, CovidCertificates.AmazonRootCA4, CovidCertificates.SFSRootCA]
    private let evaluators = [
        "covidsafe.gov.au": PinnedCertificatesTrustEvaluator(certificates: CovidNetworking.validCerts)
    ]
    
    static let shared = CovidNetworking()
    public let session: Session
    
    init() {       
        let serverTrustPolicy = CovidServerTrustManager(evaluators: evaluators)
        session = Session(serverTrustManager:serverTrustPolicy)
    }
}

enum APIError: Error {
    case ExpireSession
    case ServerError
}

struct CovidSafeErrorResponse: Decodable {
    let message: String?
}

enum CovidSafeAPIError: Error {
    case RequestError
    case ResponseError
    case ServerError
    case TokenExpiredError
    case TokenAlreadyRefreshedError
    case MaxRegistrationError
    case UnknownError
}

class CovidSafeAuthenticatedAPI {
    
    static var isBusy = false
    
    static func authenticatedHeaders() throws -> HTTPHeaders {
        let keychain = KeychainSwift.shared
        
        guard let token = keychain.get("JWT_TOKEN") else {
            throw CovidSafeAPIError.RequestError
        }
        let headers: HTTPHeaders = [
            "Authorization": "Bearer \(token)"
        ]
        return headers
    }
    
    static func processUnauthorizedError(_ data: Data) -> CovidSafeAPIError {
        var errorType = CovidSafeAPIError.RequestError
        do {
            let errorResponse = try JSONDecoder().decode(CovidSafeErrorResponse.self, from: data)
            if errorResponse.message == "Unauthorized" {
                errorType = .TokenExpiredError
            }
        } catch {
            // unable to parse response
            errorType = .ResponseError
        }
        return errorType
    }
}
