package com.doctate.watch.audio

import android.content.Context
import android.media.MediaRecorder
import android.os.Build
import java.io.File

/**
 * Thin wrapper around [MediaRecorder] producing an MPEG-4/AAC file on disk.
 * Not thread-safe: call start()/stop()/cancel() from a single coroutine scope.
 *
 * Format: 16 kHz mono AAC-LC at 64 kbps — matches Whisper's native sample rate
 * so the server-side remux can skip a resample stage.
 *
 * Writes directly into the caller-supplied target file so the pending
 * upload queue can sit on the audio without an intermediate copy. The
 * caller is responsible for choosing a path that survives crashes
 * (typically [PendingStore.audioPathFor]).
 */
class AudioRecorder(private val context: Context) {
    private var recorder: MediaRecorder? = null
    private var currentFile: File? = null

    /** Start recording into [outFile]. The parent directory is created if missing. */
    fun start(outFile: File): File {
        require(recorder == null) { "recorder already active" }
        outFile.parentFile?.takeIf { !it.exists() }?.mkdirs()
        val r = newRecorderInstance().apply {
            // VOICE_RECOGNITION lowers raw level vs MIC but applies the
            // platform's noise/echo cleaning. Combined with the
            // server-side replay-gain pass the playback ends up at
            // target loudness with cleaner SNR than raw MIC + post-gain.
            setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION)
            setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
            setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
            setAudioSamplingRate(16_000)
            setAudioEncodingBitRate(64_000)
            setAudioChannels(1)
            setOutputFile(outFile.absolutePath)
            prepare()
            start()
        }
        recorder = r
        currentFile = outFile
        return outFile
    }

    fun stop(): File {
        val r = requireNotNull(recorder) { "recorder not started" }
        val f = requireNotNull(currentFile)
        try { r.stop() } finally {
            r.release()
            recorder = null
            currentFile = null
        }
        return f
    }

    fun cancel() {
        val r = recorder ?: return
        val f = currentFile
        try { r.stop() } catch (_: RuntimeException) { /* not started or too short — ignore */ }
        r.release()
        recorder = null
        currentFile = null
        f?.delete()
    }

    private fun newRecorderInstance(): MediaRecorder =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            MediaRecorder(context)
        } else {
            @Suppress("DEPRECATION")
            MediaRecorder()
        }
}
