//
// GameStateTests.swift
// IceGlassTests
//
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
//

import Testing
@testable import IceGlass

struct GameStateTests {
    @Test func decodesFromNHLAPIRawValues() {
        #expect(GameState(rawValue: "FUT") == .future)
        #expect(GameState(rawValue: "PRE") == .pre)
        #expect(GameState(rawValue: "LIVE") == .live)
        #expect(GameState(rawValue: "CRIT") == .crit)
        #expect(GameState(rawValue: "OVER") == .over)
        #expect(GameState(rawValue: "FINAL") == .final_)
        #expect(GameState(rawValue: "OFF") == .official)
        #expect(GameState(rawValue: "BOGUS") == nil)
    }

    @Test func isLiveIsOverIsFutureAreMutuallyConsistent() {
        let allCases: [GameState] = [.future, .pre, .live, .crit, .over, .final_, .official]
        for state in allCases {
            // Each state falls into exactly one of the three buckets used to
            // drive menu/notification behavior.
            let bucketCount = [state.isFuture, state.isLive, state.isOver].filter { $0 }.count
            #expect(bucketCount == 1, "\(state) should be in exactly one of future/live/over")
        }
        #expect(GameState.future.isFuture)
        #expect(GameState.pre.isFuture)
        #expect(GameState.live.isLive)
        #expect(GameState.crit.isLive)
        #expect(GameState.over.isOver)
        #expect(GameState.final_.isOver)
        #expect(GameState.official.isOver)
    }

    @Test func progressionRankIsMonotonicAlongTheAPILifecycle() {
        // FUT → PRE → LIVE → CRIT → OVER → FINAL → OFF must never regress;
        // MainService relies on this ordering to reject stale API responses
        // that would otherwise flip a finished game back to "-:-".
        let ordered: [GameState] = [.future, .pre, .live, .crit, .over, .final_, .official]
        let ranks = ordered.map(\.progressionRank)
        #expect(ranks == ranks.sorted())
        #expect(Set(ranks).count == ranks.count, "ranks must be distinct")
    }

    @Test func progressionRankOfRawStringMatchesEnumRankAndHandlesUnknown() {
        #expect(GameState.progressionRank(of: "LIVE") == GameState.live.progressionRank)
        #expect(GameState.progressionRank(of: "OFF") == GameState.official.progressionRank)
        #expect(GameState.progressionRank(of: "NOT_A_STATE") == -1)
    }

    @Test func pollingIntervalMapsEachStateToTheExpectedCadence() {
        #expect(GameState.future.pollingInterval == .gameDay)
        #expect(GameState.pre.pollingInterval == .preGame)
        #expect(GameState.live.pollingInterval == .liveGame)
        #expect(GameState.crit.pollingInterval == .liveGame)
        #expect(GameState.over.pollingInterval == .everyMinute)
        #expect(GameState.final_.pollingInterval == .everyMinute)
        #expect(GameState.official.pollingInterval == .idle)
    }
}
