//
//  RegionTests.swift
//  SportsTimeTests
//
//  TDD specification tests for Region enum.
//

import Testing
@testable import SportsTime

@Suite("Region")
struct RegionTests {

    // MARK: - Specification Tests: classify(longitude:)

    @Test("classify: longitude > -85 returns .east")
    func classify_east() {
        // NYC: -73.9855
        #expect(Region.classify(longitude: -73.9855) == .east)

        // Boston: -71.0972
        #expect(Region.classify(longitude: -71.0972) == .east)

        // Miami: -80.1918
        #expect(Region.classify(longitude: -80.1918) == .east)

        // Toronto: -79.3832
        #expect(Region.classify(longitude: -79.3832) == .east)

        // Atlanta: -84.3880
        #expect(Region.classify(longitude: -84.3880) == .east)

        // Just above boundary
        #expect(Region.classify(longitude: -84.9999) == .east)
    }

    @Test("classify: longitude in -110...-85 returns .central")
    func classify_central() {
        // Chicago: -87.6233
        #expect(Region.classify(longitude: -87.6233) == .central)

        // Houston: -95.3698
        #expect(Region.classify(longitude: -95.3698) == .central)

        // Dallas: -96.7970
        #expect(Region.classify(longitude: -96.7970) == .central)

        // Minneapolis: -93.2650
        #expect(Region.classify(longitude: -93.2650) == .central)

        // Denver: -104.9903
        #expect(Region.classify(longitude: -104.9903) == .central)

        // Boundary: exactly -85
        #expect(Region.classify(longitude: -85.0) == .central)

        // Boundary: exactly -110
        #expect(Region.classify(longitude: -110.0) == .central)
    }

    @Test("classify: longitude < -110 returns .west")
    func classify_west() {
        // Los Angeles: -118.2673
        #expect(Region.classify(longitude: -118.2673) == .west)

        // San Francisco: -122.4194
        #expect(Region.classify(longitude: -122.4194) == .west)

        // Seattle: -122.3321
        #expect(Region.classify(longitude: -122.3321) == .west)

        // Phoenix: -112.0740
        #expect(Region.classify(longitude: -112.0740) == .west)

        // Las Vegas: -115.1398
        #expect(Region.classify(longitude: -115.1398) == .west)

        // Just below boundary
        #expect(Region.classify(longitude: -110.0001) == .west)
    }

    // MARK: - Specification Tests: Boundary Values

    @Test("classify boundary: -85 is central, -84.9999 is east")
    func classify_eastCentralBoundary() {
        #expect(Region.classify(longitude: -85.0) == .central)
        #expect(Region.classify(longitude: -84.9999) == .east)
        #expect(Region.classify(longitude: -85.0001) == .central)
    }

    @Test("classify boundary: -110 is central, -110.0001 is west")
    func classify_centralWestBoundary() {
        #expect(Region.classify(longitude: -110.0) == .central)
        #expect(Region.classify(longitude: -109.9999) == .central)
        #expect(Region.classify(longitude: -110.0001) == .west)
    }

    // MARK: - Specification Tests: Edge Cases

    @Test("classify: extreme east longitude (positive) returns .east")
    func classify_extremeEast() {
        #expect(Region.classify(longitude: 0.0) == .east)
        #expect(Region.classify(longitude: 50.0) == .east)
    }

    @Test("classify: extreme west longitude returns .west")
    func classify_extremeWest() {
        #expect(Region.classify(longitude: -180.0) == .west)
        #expect(Region.classify(longitude: -150.0) == .west)
    }

    // MARK: - Invariant Tests

    @Test("Invariant: classify never returns .crossCountry")
    func invariant_classifyNeverReturnsCrossCountry() {
        let testLongitudes: [Double] = [-180, -150, -120, -110.0001, -110, -100, -85.0001, -85, -70, 0, 50]
        for lon in testLongitudes {
            let region = Region.classify(longitude: lon)
            #expect(region != .crossCountry, "classify should never return crossCountry for longitude \(lon)")
        }
    }

    @Test("Invariant: every longitude maps to exactly one region")
    func invariant_everyLongitudeMapsToOneRegion() {
        // Test a range of longitudes
        for lon in stride(from: -180.0, through: 50.0, by: 10.0) {
            let region = Region.classify(longitude: lon)
            #expect([Region.east, .central, .west].contains(region), "Longitude \(lon) should map to east, central, or west")
        }
    }

    // MARK: - Property Tests

    @Test("Property: id equals rawValue")
    func property_idEqualsRawValue() {
        for region in Region.allCases {
            #expect(region.id == region.rawValue)
        }
    }

    @Test("Property: displayName equals rawValue")
    func property_displayNameEqualsRawValue() {
        for region in Region.allCases {
            #expect(region.displayName == region.rawValue)
        }
    }

    @Test("Property: all regions have iconName")
    func property_allRegionsHaveIconName() {
        for region in Region.allCases {
            #expect(!region.iconName.isEmpty)
        }
    }

    // MARK: - Specification Tests: Display Properties

    @Test("shortName values are correct")
    func shortName_values() {
        #expect(Region.east.shortName == "East")
        #expect(Region.central.shortName == "Central")
        #expect(Region.west.shortName == "West")
        #expect(Region.crossCountry.shortName == "Coast to Coast")
    }
}
