//
// Copyright (c) Double Symmetry GmbH
// Commercial use requires a license. See https://rntp.dev/pricing
//

import XCTest

@testable import PlayerCore

// MARK: - Sleep Timer AudioPlayer Volume Clamping Tests
//
// The sleep timer sets and restores volume through AudioPlayer.volume, which
// clamps values to [0, 1]. These tests verify that clamping so the fade can
// never accidentally leave the player in an invalid state.
//
// The fade formula and state-machine logic are covered by SleepTimerIntegrationTests,
// which test the real SleepTimerController with AudioPlayer + MockPlayerEngine.

final class SleepTimerTests: XCTestCase {

    // MARK: - AudioPlayer Volume Clamping

    private var engine: MockPlayerEngine!
    private var player: AudioPlayer!

    override func setUp() {
        super.setUp()
        engine = MockPlayerEngine()
        player = AudioPlayer(engine: engine)
    }

    func testPlayerVolumeClampedAboveOne() {
        player.volume = 2.0
        XCTAssertEqual(engine.volume, 1.0,
            "sleep timer setting volume above 1.0 must be clamped")
    }

    func testPlayerVolumeClampedBelowZero() {
        player.volume = -0.5
        XCTAssertEqual(engine.volume, 0.0,
            "sleep timer setting volume below 0 must be clamped")
    }

    func testPlayerVolumeAtZeroIsExactlyZero() {
        player.volume = 0.0
        XCTAssertEqual(engine.volume, 0.0)
    }

    func testPlayerVolumeAtOneIsExactlyOne() {
        player.volume = 1.0
        XCTAssertEqual(engine.volume, 1.0)
    }

    func testPlayerVolumeSetToFadedValue() {
        // Simulate what the sleep timer does: set a mid-fade volume (0.8 * 0.25 = 0.2)
        let fadedVolume: Float = 0.8 * Float(5.0 / 20.0)
        player.volume = fadedVolume
        XCTAssertEqual(engine.volume, fadedVolume, accuracy: 0.0001)
    }

    func testPlayerVolumeRestoredAfterFade() {
        // Simulate: pre-fade volume captured at 0.8, fade runs to 0, then restore.
        let preFadeVolume: Float = 0.8
        player.volume = 0.0          // volume after fade completes
        XCTAssertEqual(engine.volume, 0.0)

        player.volume = preFadeVolume  // sleep timer restore on cancel/completion
        XCTAssertEqual(engine.volume, preFadeVolume, accuracy: 0.0001)
    }
}
