import XCTest
@testable import RideFormCore

final class SamplingStatisticsTests: XCTestCase {
    func testRegularAndInsufficientStreams() {
        let result = SamplingStatistics.calculate(timestamps: (0...10).map { Double($0) * 0.01 })
        XCTAssertEqual(result.count, 11)
        XCTAssertEqual(result.durationSeconds!, 0.1, accuracy: 1e-12)
        XCTAssertEqual(result.meanHz!, 100, accuracy: 1e-10)
        XCTAssertEqual(result.medianHz!, 100, accuracy: 1e-10)
        XCTAssertEqual(result.intervalStandardDeviationSeconds!, 0, accuracy: 1e-12)
        XCTAssertNil(SamplingStatistics.calculate(timestamps: []).meanHz)
        XCTAssertNil(SamplingStatistics.calculate(timestamps: [1]).medianHz)
    }
    func testOriginalOrderAndGapEstimate() {
        let times = [0.0, 1, 1, 0.5, 1.5, 5.5]
        let result = SamplingStatistics.calculate(timestamps: times)
        XCTAssertEqual(result.count, 6)
        XCTAssertEqual(result.nonpositiveIntervalCount, 2)
        XCTAssertEqual(result.meanHz!, 5 / 5.5, accuracy: 1e-12)
        XCTAssertEqual(result.medianHz, 1)
        XCTAssertEqual(result.p95IntervalSeconds, 4)
        XCTAssertEqual(result.p99IntervalSeconds, 4)
        XCTAssertEqual(result.intervalStandardDeviationSeconds!, sqrt(2), accuracy: 1e-12)
        XCTAssertEqual(result.gapThresholdSeconds, 2.5)
        XCTAssertEqual(result.gapCount, 1)
        XCTAssertEqual(result.gapPercentage!, 100 / 3, accuracy: 1e-12)
        XCTAssertEqual(result.estimatedMissingIntervals, 3)
        XCTAssertEqual(times, [0, 1, 1, 0.5, 1.5, 5.5])
    }
    func testDeliveryAgeRequiresValidatedMapping() {
        let times = [1.0, 2, 3]
        let receipt = [1.2, 2.4, 3.7]
        XCTAssertTrue(SamplingStatistics.calculate(timestamps: times, receiptUptimes: receipt).deliveryAgeSeconds.isEmpty)
        let result = SamplingStatistics.calculate(timestamps: times, receiptUptimes: receipt, clockMapping: ClockMapping(sensorToHostOffset: 0, validated: true))
        XCTAssertEqual(result.meanHz, 1)
        for (actual, expected) in zip(result.deliveryAgeSeconds, [0.2, 0.4, 0.7]) { XCTAssertEqual(actual, expected, accuracy: 1e-12) }
    }
}
