//
//  MeowTests.swift
//  MeowTests
//

import Foundation
import Testing
import Mocker
@testable import CatFactsKit

@Suite("CatFacts Tests")
struct CatFactsTests {
    private let baseURL = URL(string: "https://meow.meow")!
    let urlSession: URLSession = {
        let configuration = URLSessionConfiguration.default
        configuration.protocolClasses = [MockingURLProtocol.self]
        return URLSession(configuration: configuration)
    }()

    @Test("constructor retains baseURL")
    func constructor() async throws {
        let instance = vendInstance()
        #expect(instance.baseURL == baseURL)
    }

    @Test("getFacts calls the appropriate API and returns a result")
    func getFacts() async throws {
        let instance = vendInstance()
        let count = 5
        mockPath("/", queryItems: ["count": count], data: [.get: Fixtures.facts])
        let facts = try await instance.getFacts(count: count)
        #expect(facts.count == count)
        #expect(facts[3] == "The average cat food meal is the equivalent to about five mice.")
    }

    // MARK: - Private functionality

    private func vendInstance() -> CatFacts {
        return CatFacts(baseURL: baseURL, urlSession: urlSession)
    }

    private func mockPath(_ path: String, headers: [String: String] = [:], queryItems: [String: CustomStringConvertible] = [:], data: [Mock.HTTPMethod: Data] = [:]) {
        let urlQueryItems = queryItems
            .compactMap({ URLQueryItem(name: $0, value: $1.description) })
            .sorted { a, b in a.name < b.name }
        let base = baseURL.appendingPathComponent(path)
        let url = urlQueryItems.isEmpty ? base : base.appending(queryItems: urlQueryItems)
        Mock(url: url, ignoreQuery: false, contentType: .json, statusCode: 200, data: data, additionalHeaders: headers).register()
    }
}
