//
//  PhotoMetadataExtractorTests.swift
//  SportsTimeTests
//
//  TDD specification tests for PhotoMetadata types.
//

import Testing
import Foundation
import CoreLocation
@testable import SportsTime

// MARK: - PhotoMetadata Tests

@Suite("PhotoMetadata")
struct PhotoMetadataTests {

    // MARK: - Test Data

    private func makeMetadata(
        captureDate: Date? = Date(),
        coordinates: CLLocationCoordinate2D? = CLLocationCoordinate2D(latitude: 40.0, longitude: -74.0)
    ) -> PhotoMetadata {
        PhotoMetadata(captureDate: captureDate, coordinates: coordinates)
    }

    // MARK: - Specification Tests: hasValidLocation

    /// - Expected Behavior: true when coordinates are provided
    @Test("hasValidLocation: true when coordinates provided")
    func hasValidLocation_true() {
        let metadata = makeMetadata(coordinates: CLLocationCoordinate2D(latitude: 40.0, longitude: -74.0))
        #expect(metadata.hasValidLocation == true)
    }

    /// - Expected Behavior: false when coordinates are nil
    @Test("hasValidLocation: false when coordinates nil")
    func hasValidLocation_false() {
        let metadata = makeMetadata(coordinates: nil)
        #expect(metadata.hasValidLocation == false)
    }

    // MARK: - Specification Tests: hasValidDate

    /// - Expected Behavior: true when captureDate is provided
    @Test("hasValidDate: true when captureDate provided")
    func hasValidDate_true() {
        let metadata = makeMetadata(captureDate: Date())
        #expect(metadata.hasValidDate == true)
    }

    /// - Expected Behavior: false when captureDate is nil
    @Test("hasValidDate: false when captureDate nil")
    func hasValidDate_false() {
        let metadata = makeMetadata(captureDate: nil)
        #expect(metadata.hasValidDate == false)
    }

    // MARK: - Specification Tests: empty

    /// - Expected Behavior: empty returns metadata with all nil values
    @Test("empty: returns metadata with nil captureDate")
    func empty_nilCaptureDate() {
        let empty = PhotoMetadata.empty
        #expect(empty.captureDate == nil)
    }

    @Test("empty: returns metadata with nil coordinates")
    func empty_nilCoordinates() {
        let empty = PhotoMetadata.empty
        #expect(empty.coordinates == nil)
    }

    @Test("empty: returns metadata with hasValidLocation false")
    func empty_hasValidLocationFalse() {
        let empty = PhotoMetadata.empty
        #expect(empty.hasValidLocation == false)
    }

    @Test("empty: returns metadata with hasValidDate false")
    func empty_hasValidDateFalse() {
        let empty = PhotoMetadata.empty
        #expect(empty.hasValidDate == false)
    }

    // MARK: - Specification Tests: Combinations

    @Test("Both valid: location and date both provided")
    func bothValid() {
        let metadata = makeMetadata(captureDate: Date(), coordinates: CLLocationCoordinate2D(latitude: 0, longitude: 0))
        #expect(metadata.hasValidLocation == true)
        #expect(metadata.hasValidDate == true)
    }

    @Test("Only location: date nil")
    func onlyLocation() {
        let metadata = makeMetadata(captureDate: nil, coordinates: CLLocationCoordinate2D(latitude: 0, longitude: 0))
        #expect(metadata.hasValidLocation == true)
        #expect(metadata.hasValidDate == false)
    }

    @Test("Only date: coordinates nil")
    func onlyDate() {
        let metadata = makeMetadata(captureDate: Date(), coordinates: nil)
        #expect(metadata.hasValidLocation == false)
        #expect(metadata.hasValidDate == true)
    }

    // MARK: - Invariant Tests

    /// - Invariant: hasValidLocation == (coordinates != nil)
    @Test("Invariant: hasValidLocation equals coordinates check")
    func invariant_hasValidLocationEqualsCoordinatesCheck() {
        let withCoords = makeMetadata(coordinates: CLLocationCoordinate2D(latitude: 0, longitude: 0))
        let withoutCoords = makeMetadata(coordinates: nil)

        #expect(withCoords.hasValidLocation == (withCoords.coordinates != nil))
        #expect(withoutCoords.hasValidLocation == (withoutCoords.coordinates != nil))
    }

    /// - Invariant: hasValidDate == (captureDate != nil)
    @Test("Invariant: hasValidDate equals captureDate check")
    func invariant_hasValidDateEqualsCaptureCheck() {
        let withDate = makeMetadata(captureDate: Date())
        let withoutDate = makeMetadata(captureDate: nil)

        #expect(withDate.hasValidDate == (withDate.captureDate != nil))
        #expect(withoutDate.hasValidDate == (withoutDate.captureDate != nil))
    }

    /// - Invariant: empty.hasValidLocation && empty.hasValidDate == false
    @Test("Invariant: empty has no valid data")
    func invariant_emptyHasNoValidData() {
        let empty = PhotoMetadata.empty
        #expect(!empty.hasValidLocation && !empty.hasValidDate)
    }
}
