import Foundation
import AVFoundation
import RideFormCore

@MainActor
final class CuePlayer {
    private let now: () -> Double
    private let schedule: (Double, @escaping @MainActor @Sendable () -> Void) -> Void
    private let speak: (String) -> Void
    private let synthesizer: AVSpeechSynthesizer
    private var generation = 0
    private(set) var active = false
    init(now: @escaping () -> Double = { SessionClock().now() }, schedule: @escaping (Double, @escaping @MainActor @Sendable () -> Void) -> Void = { delay, job in DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: job) }, speak: ((String) -> Void)? = nil) {
        let synthesizer = AVSpeechSynthesizer()
        self.synthesizer = synthesizer
        self.now = now; self.schedule = schedule
        self.speak = speak ?? { label in
            let utterance = AVSpeechUtterance(string: label)
            utterance.rate = 0.45
            synthesizer.speak(utterance)
        }
    }
    func start(onEvent: @escaping (EventMarker) -> Void) {
        cancel(); active = true
        let token = generation, anchor = now()
        for (index, label) in ["CENTER", "LEFT", "CENTER", "RIGHT", "CENTER"].enumerated() {
            let delay = Double(index) * 3
            schedule(delay) { [weak self] in
                guard let self, self.active, self.generation == token else { return }
                let actual = self.now()
                self.speak(label)
                onEvent(EventMarker(kind: "cue", label: label, hostUptime: actual, scheduledUptime: anchor + delay, audioDispatchUptime: actual, note: "Speech dispatch; acoustic onset unmeasured"))
                if index == 4 { self.active = false }
            }
        }
    }
    func cancel() {
        generation += 1; active = false
        synthesizer.stopSpeaking(at: .immediate)
    }
}
