import Testing
import MusicModel
@testable import AudioCore

@Suite struct MeterChangeSchedulingTests {
    let sr = 48000.0

    /// 3/4 → one 4/4 measure → 3/4, at 120 bpm (quarter = 24 000 samples).
    private func score() throws -> Score {
        try Acasong.parse("""
        acasong 1
        title: M
        time: 3/4
        time@2: 4/4
        time@3: 3/4
        key: C major
        tempo: 120

        part S
        C4 2. | D4 1 | E4 2.
        """)
    }

    @Test func noteSamplesRespectMeterChange() throws {
        let program = try ProgramCompiler.compile(score: try score(), options: .init(sampleRate: sr))
        let events = program.tracks[0].events
        #expect(events[0].startSample == 0)
        #expect(events[1].startSample == 72_000)                 // after 3/4 measure
        #expect(events[2].startSample == 72_000 + 96_000)       // after 4/4 measure
        #expect(program.endSample == 72_000 + 96_000 + 72_000)
    }

    @Test func metronomeFollowsEachMeasuresMeter() throws {
        let program = try ProgramCompiler.compile(
            score: try score(),
            options: .init(sampleRate: sr, metronomeDuringPlayback: true)
        )
        // 3 + 4 + 3 clicks.
        #expect(program.clicks.count == 10)
        let strongs = program.clicks.filter(\.isStrong).map(\.sample)
        #expect(strongs == [0, 72_000, 168_000])   // downbeat of each measure
        // The 4/4 measure's clicks are all inside it.
        let inFourFour = program.clicks.filter { $0.sample >= 72_000 && $0.sample < 168_000 }
        #expect(inFourFour.count == 4)
    }

    @Test func countInUsesMeterOfStartMeasure() throws {
        // Count-in before the 4/4 measure must be one 4/4 measure long.
        let program = try ProgramCompiler.compile(
            score: try score(),
            options: .init(sampleRate: sr, countIn: true, measureRange: 1...1)
        )
        #expect(program.firstSample == -96_000)
        #expect(program.clicks.count == 4)
        #expect(program.clicks.first?.sample == -96_000)
    }
}
