//
//  PollServiceTests.swift
//  SportsTimeTests
//
//  TDD specification tests for PollService types.
//

import Testing
import Foundation
@testable import SportsTime

// MARK: - PollError Tests

@Suite("PollError")
struct PollErrorTests {

    // MARK: - Specification Tests: errorDescription

    /// - Expected Behavior: notSignedIn explains iCloud requirement
    @Test("errorDescription: notSignedIn mentions iCloud")
    func errorDescription_notSignedIn() {
        let error = PollError.notSignedIn
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("icloud") || error.errorDescription!.lowercased().contains("sign in"))
    }

    /// - Expected Behavior: pollNotFound explains poll doesn't exist
    @Test("errorDescription: pollNotFound mentions not found")
    func errorDescription_pollNotFound() {
        let error = PollError.pollNotFound
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("not found") || error.errorDescription!.lowercased().contains("deleted"))
    }

    /// - Expected Behavior: alreadyVoted explains duplicate vote
    @Test("errorDescription: alreadyVoted mentions already voted")
    func errorDescription_alreadyVoted() {
        let error = PollError.alreadyVoted
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("already voted"))
    }

    /// - Expected Behavior: notPollOwner explains ownership requirement
    @Test("errorDescription: notPollOwner mentions owner")
    func errorDescription_notPollOwner() {
        let error = PollError.notPollOwner
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("owner"))
    }

    /// - Expected Behavior: networkUnavailable explains connection issue
    @Test("errorDescription: networkUnavailable mentions connection")
    func errorDescription_networkUnavailable() {
        let error = PollError.networkUnavailable
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("connect") || error.errorDescription!.lowercased().contains("internet"))
    }

    /// - Expected Behavior: encodingError explains save failure
    @Test("errorDescription: encodingError mentions save")
    func errorDescription_encodingError() {
        let error = PollError.encodingError
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("save") || error.errorDescription!.lowercased().contains("failed"))
    }

    /// - Expected Behavior: unknown includes underlying error message
    @Test("errorDescription: unknown includes underlying error")
    func errorDescription_unknown() {
        let underlyingError = NSError(domain: "TestDomain", code: 123, userInfo: [NSLocalizedDescriptionKey: "Test underlying error"])
        let error = PollError.unknown(underlyingError)
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.contains("Test underlying error") || error.errorDescription!.lowercased().contains("error"))
    }

    // MARK: - Invariant Tests

    /// - Invariant: All errors have non-empty descriptions
    @Test("Invariant: all errors have descriptions")
    func invariant_allHaveDescriptions() {
        let errors: [PollError] = [
            .notSignedIn,
            .pollNotFound,
            .alreadyVoted,
            .notPollOwner,
            .networkUnavailable,
            .encodingError,
            .unknown(NSError(domain: "", code: 0))
        ]

        for error in errors {
            #expect(error.errorDescription != nil)
            #expect(!error.errorDescription!.isEmpty)
        }
    }

    /// - Invariant: All non-unknown errors have distinct descriptions
    @Test("Invariant: non-unknown errors have distinct descriptions")
    func invariant_distinctDescriptions() {
        let errors: [PollError] = [
            .notSignedIn,
            .pollNotFound,
            .alreadyVoted,
            .notPollOwner,
            .networkUnavailable,
            .encodingError
        ]

        let descriptions = errors.compactMap { $0.errorDescription }
        let uniqueDescriptions = Set(descriptions)

        #expect(descriptions.count == uniqueDescriptions.count)
    }
}
