//
//  VisitPhotoServiceTests.swift
//  SportsTimeTests
//
//  TDD specification tests for VisitPhotoService types.
//

import Testing
import Foundation
@testable import SportsTime

// MARK: - PhotoServiceError Tests

@Suite("PhotoServiceError")
struct PhotoServiceErrorTests {

    // MARK: - Specification Tests: errorDescription

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

    /// - Expected Behavior: uploadFailed includes the message
    @Test("errorDescription: uploadFailed includes message")
    func errorDescription_uploadFailed() {
        let error = PhotoServiceError.uploadFailed("Network timeout")
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.contains("Network timeout") || error.errorDescription!.lowercased().contains("upload"))
    }

    /// - Expected Behavior: downloadFailed includes the message
    @Test("errorDescription: downloadFailed includes message")
    func errorDescription_downloadFailed() {
        let error = PhotoServiceError.downloadFailed("Connection lost")
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.contains("Connection lost") || error.errorDescription!.lowercased().contains("download"))
    }

    /// - Expected Behavior: thumbnailGenerationFailed explains the issue
    @Test("errorDescription: thumbnailGenerationFailed mentions thumbnail")
    func errorDescription_thumbnailGenerationFailed() {
        let error = PhotoServiceError.thumbnailGenerationFailed
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("thumbnail"))
    }

    /// - Expected Behavior: invalidImage explains invalid data
    @Test("errorDescription: invalidImage mentions invalid")
    func errorDescription_invalidImage() {
        let error = PhotoServiceError.invalidImage
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("invalid"))
    }

    /// - Expected Behavior: assetNotFound explains missing photo
    @Test("errorDescription: assetNotFound mentions not found")
    func errorDescription_assetNotFound() {
        let error = PhotoServiceError.assetNotFound
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("not found") || error.errorDescription!.lowercased().contains("photo"))
    }

    /// - Expected Behavior: quotaExceeded explains storage limit
    @Test("errorDescription: quotaExceeded mentions quota")
    func errorDescription_quotaExceeded() {
        let error = PhotoServiceError.quotaExceeded
        #expect(error.errorDescription != nil)
        #expect(error.errorDescription!.lowercased().contains("quota") || error.errorDescription!.lowercased().contains("storage"))
    }

    // MARK: - Invariant Tests

    /// - Invariant: All errors have non-empty descriptions
    @Test("Invariant: all errors have descriptions")
    func invariant_allHaveDescriptions() {
        let errors: [PhotoServiceError] = [
            .notSignedIn,
            .uploadFailed("test"),
            .downloadFailed("test"),
            .thumbnailGenerationFailed,
            .invalidImage,
            .assetNotFound,
            .quotaExceeded
        ]

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

    /// - Invariant: uploadFailed and downloadFailed preserve their messages
    @Test("Invariant: parameterized errors preserve message")
    func invariant_parameterizedErrorsPreserveMessage() {
        let testMessage = "Test error message 12345"

        let uploadError = PhotoServiceError.uploadFailed(testMessage)
        let downloadError = PhotoServiceError.downloadFailed(testMessage)

        // The message should appear somewhere in the description
        #expect(uploadError.errorDescription!.contains(testMessage))
        #expect(downloadError.errorDescription!.contains(testMessage))
    }
}
