//
//  RazerNetworkingTests.swift
//  
//
//  Created by Swee Kwang Chua on 10/3/22.
//

import XCTest
@testable import RazerCore

// USING MOCK NETWORK FOR TESTING
class NetworkSessionMock: NetworkSession {
    var data: Data?
    var error: Error?
    
    func get(from url: URL, completionHandler: @escaping (Data?, Error?) -> Void) {
        // OVER HERE SHOULD ADD THE BUSINEES LOGIC FOR TESTING PURPOSES
        completionHandler(data, error)
    }
    
    func post(with request: URLRequest, completionHandler: @escaping (Data?, Error?) -> Void) {
        // OVER HERE SHOULD ADD THE BUSINEES LOGIC FOR TESTING PURPOSES
        completionHandler(data, error)
    }
}

struct MockData: Codable, Equatable {
    var id: Int
    var name: String
}

final class RazerNetworkingTests: XCTestCase {
    
//    func testLoadDataCall(){
//        let manager = RazerCore.Networking.Manager()
//        let expectation = XCTestExpectation(description: "Called for data")
//        guard let url = URL(string: "https://sweekwang.com") else {
//            return XCTFail("Chould not create URL properly")
//        }
//        manager.loadData(from: url) { result in
//            expectation.fulfill()
//            switch result {
//            case .success(let data):
//                XCTAssertNotNil(data, "Response data is nil")
//            case .failure(let error):
//                XCTFail(error?.localizedDescription ?? "error forming error result")
//            }
//        }
//        wait(for: [expectation], timeout: 5)
//    }
    
    func testLoadDataCall(){
        // ABLE TO SIMULATE NETWORK IF THE INTERNET CANNOT BE REACHED.
        let manager = RazerCore.Networking.Manager()
        let session = NetworkSessionMock()
        manager.session = session
        let expectation = XCTestExpectation(description: "Called for data")
        let data = Data([0, 1, 0, 1])
        session.data = data
        let url = URL(fileURLWithPath: "url")
        manager.loadData(from: url) { result in
            expectation.fulfill()
            switch result {
            case .success(let returnedData):
                XCTAssertEqual(data, returnedData, "manager returned unexpected data")
            case .failure(let error):
                XCTFail(error?.localizedDescription ?? "error forming error result")
            }
        }
        wait(for: [expectation], timeout: 5)
    }
    
    func testSendDataCall() {
        let session = NetworkSessionMock()
        let manager = RazerCore.Networking.Manager()
        let sampleObject = MockData(id: 1, name: "David")
        let data = try? JSONEncoder().encode(sampleObject)
        session.data = data
        manager.session = session
        let url = URL(fileURLWithPath: "url")
        let expectation = XCTestExpectation(description: "Sent data")
        manager.sendData(to: url, body: sampleObject) { result in
            expectation.fulfill()
            switch result {
            case .success(let returnedData):
                let returnedObject = try? JSONDecoder().decode(MockData.self, from: returnedData)
                XCTAssertEqual(returnedObject, sampleObject)
                break
            case .failure(let error):
                XCTFail(error?.localizedDescription ?? "error forming error result")
                
            }
        }
        wait(for: [expectation], timeout: 5)
        
    }

}
