import Foundation
import IndieBackup
import SwiftData

/// Owns all service objects; created asynchronously at launch and injected
/// into the SwiftUI environment.
@Observable
@MainActor
final class AppServices {
    let modelContainer: ModelContainer
    let syncEngine: SyncEngine
    let contextService: ContextService
    let backupController: BackupController
    let audioRecorder: AudioRecorderService
    let transcriptionSettings: TranscriptionSettings
    let transcriptionService: TranscriptionService

    init() async {
        let container = NotesModelContainer.make()
        self.modelContainer = container
        let engine = SyncEngine(modelContainer: container)
        self.syncEngine = engine
        self.contextService = ContextService()
        self.backupController = BackupController(
            configuration: NotesBackupConfiguration(syncEngine: engine)
        )
        self.audioRecorder = AudioRecorderService()
        let settings = TranscriptionSettings()
        self.transcriptionSettings = settings
        let transcription = TranscriptionService(
            syncEngine: engine,
            settings: settings,
            modelContainer: container
        )
        self.transcriptionService = transcription

        // A watch recording, once ingested, is this device's to transcribe.
        engine.onAudioNoteIngested = { [weak transcription] id in
            transcription?.enqueue(noteID: id)
        }
    }

    /// The file extension this app owns for backup documents. Used to route
    /// `onOpenURL` imports to a restore.
    var backupFileExtension: String { backupController.configuration.backupFileExtension }

    /// Slow startup work (iCloud container discovery) — runs after the UI is up.
    func startDeferredServices() async {
        await syncEngine.connect()
        // Drain any watch recordings delivered while the app was closed — the
        // container is connected now, so they can be written and ingested.
        await syncEngine.ingestStagedWatchRecordings()
        // Load the supported languages / reservation cap, then pick up any of
        // this device's notes that were still pending when it last quit.
        await transcriptionSettings.prepare()
        transcriptionService.resumePendingWork()
    }
}
