import Foundation
import Testing
@testable import Workouts

/// Pins the live-mirror staleness ordering (`LiveProgress.isNewer`): the shared per-run
/// version sequence decides, and the phase anchor breaks ties. The tie-break exists
/// because the sequence isn't collision-free — each side catches its counter up only from
/// frames it *receives*, so after a lost frame both devices can mint the same version
/// independently, and the later wall-clock action must win. Equal version *and* equal
/// anchor is the same frame redelivered, which must NOT rank as newer (a redelivery would
/// otherwise re-jump the follower's page).
struct LiveProgressOrderingTests {
    private static let t0 = Date(timeIntervalSince1970: 1_700_000_000)

    private func frame(version: Int, start: Date) -> LiveProgress {
        LiveProgress(workoutID: "W", logID: "L", exerciseName: "Bench", phase: .work,
                     setIndex: 0, setCount: 3, detail: "8 reps",
                     phaseStart: start, phaseEnd: nil, version: version)
    }

    @Test func higherVersionWinsRegardlessOfAnchor() {
        let older = frame(version: 3, start: Self.t0.addingTimeInterval(10))
        let newer = frame(version: 4, start: Self.t0)   // earlier anchor, higher version
        #expect(newer.isNewer(than: older))
        #expect(!older.isNewer(than: newer))
    }

    @Test func collidedVersionsTieBreakOnAnchor() {
        let phoneFrame = frame(version: 4, start: Self.t0)
        let watchFrame = frame(version: 4, start: Self.t0.addingTimeInterval(2))
        #expect(watchFrame.isNewer(than: phoneFrame))
        #expect(!phoneFrame.isNewer(than: watchFrame))
    }

    @Test func redeliveryIsNotNewer() {
        let sent = frame(version: 4, start: Self.t0)
        #expect(!sent.isNewer(than: sent))
    }

    @Test func versionAndStartOverloadMatchesFrameOverload() {
        let f = frame(version: 4, start: Self.t0)
        #expect(f.isNewer(thanVersion: 3, start: Self.t0.addingTimeInterval(99)))
        #expect(f.isNewer(thanVersion: 4, start: Self.t0.addingTimeInterval(-1)))
        #expect(!f.isNewer(thanVersion: 4, start: Self.t0))
        #expect(!f.isNewer(thanVersion: 5, start: .distantPast))
    }
}
