// manager/CallRecordManager.kt
package com.example.initiateaphonecallapp.manager

import android.content.ContentUris
import android.content.Context
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.provider.MediaStore
import android.util.Log
import com.example.initiateaphonecallapp.data.model.AudioFile
import com.example.initiateaphonecallapp.data.model.CallRecord
import com.example.initiateaphonecallapp.data.model.SelectedAudioFile
import com.example.initiateaphonecallapp.data.repository.UploadRepository
import com.example.initiateaphonecallapp.enums.CallStatus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.util.Date
import java.util.UUID

object CallRecordManager {
    private val _callRecords = MutableStateFlow<List<CallRecord>>(emptyList())
    val callRecords: StateFlow<List<CallRecord>> = _callRecords.asStateFlow()

    private val _currentCall = MutableStateFlow<CallRecord?>(null)
    val currentCall: StateFlow<CallRecord?> = _currentCall.asStateFlow()

    // 最近一次通话记录（等待上传）
    private val _recentCall = MutableStateFlow<CallRecord?>(null)
    val recentCall: StateFlow<CallRecord?> = _recentCall.asStateFlow()

    // 上传状态
    private val _uploadStatus = MutableStateFlow<UploadStatus>(UploadStatus.IDLE)
    val uploadStatus: StateFlow<UploadStatus> = _uploadStatus.asStateFlow()

    // 选择的音频文件状态流
    private val _selectedAudioFile = MutableStateFlow<SelectedAudioFile?>(null)
    val selectedAudioFile: StateFlow<SelectedAudioFile?> = _selectedAudioFile.asStateFlow()

    // 上传仓库
    private var uploadRepository: UploadRepository? = null

    // 协程作用域
    private val scope = CoroutineScope(Dispatchers.IO)

    enum class UploadStatus {
        IDLE,           // 空闲
        UPLOADING,      // 上传中
        SUCCESS,        // 成功
        FAILED          // 失败
    }

    // 初始化方法，必须在 Application 或 Activity 中调用
    fun initialize(context: Context) {
        if (uploadRepository == null) {
            uploadRepository = UploadRepository(context)
            println("✅ CallRecordManager: 初始化完成")
        }
    }

    // 设置选择的音频文件
    fun setSelectedAudioFile(audioFile: SelectedAudioFile?) {
        _selectedAudioFile.value = audioFile
        println("🎵 CallRecordManager: 设置音频文件: ${audioFile?.fileName ?: "无"}")

        // 当选择文件后，检查是否有最近的通话记录需要关联并上传
        _recentCall.value?.let { recentCall ->
            // 只有在通话已接通的情况下才关联音频文件
            var s = recentCall.status == CallStatus.COMPLETED;
            if (recentCall.status == CallStatus.COMPLETED &&
                !recentCall.uploaded &&
                recentCall.audioFileName == null) {
                println("🔄 CallRecordManager: 发现已接通的通话记录，准备关联音频文件并上传")
                updateAndUploadCallRecord(recentCall, audioFile)
            }
        }
    }

    // 获取当前选择的音频文件（添加这个方法）
    fun getSelectedAudioFile(): SelectedAudioFile? {
        return _selectedAudioFile.value
    }

    // 开始通话记录
    fun startCallRecord(phoneNumber: String) {
        val callRecord = CallRecord(
            id = UUID.randomUUID().toString(),
            phoneNumber = phoneNumber,
            startTime = Date(),
            status = CallStatus.DIALING
            // 注意：这里不设置音频文件，等待用户选择后再关联
        )

        _currentCall.value = callRecord
        println("📞 CallRecordManager: 开始通话记录 - 号码: $phoneNumber")
    }

    // 更新通话状态为连接
    fun updateCallToConnected() {
        _currentCall.value?.let { current ->
            val updatedRecord = current.copy(
                status = CallStatus.CONNECTED
            )
            _currentCall.value = updatedRecord
            println("📞 CallRecordManager: 通话已连接")
        }
    }

    fun endCallRecord() {
        _currentCall.value?.let { current ->
            val endTime = Date()
            val duration = 0L

            val completedCall = current.copy(
                endTime = endTime,
                duration = duration,
                status = if (current.status == CallStatus.CONNECTED) {
                    CallStatus.COMPLETED
                } else {
                    CallStatus.NOT_CONNECTED // 未接通状态
                }
            )

            // 保存为最近通话记录（等待上传）
            _recentCall.value = completedCall
            _currentCall.value = null

            println("📞 CallRecordManager: 通话结束 - 号码: ${completedCall.phoneNumber}, " +
                    "时长: ${completedCall.formattedDuration}, " +
                    "状态: ${completedCall.status}")

            // 根据通话状态决定是否查找录音文件
            if (completedCall.status == CallStatus.COMPLETED) {
                // 已接通：自动查找并关联录音文件
                scope.launch {
                    autoFindAndLinkCallRecord(completedCall)
                }
            } else {
                // 未接通：直接上传通话记录（不关联录音文件）
                println("📞 CallRecordManager: 通话未接通，直接上传记录")
                uploadCallRecord(completedCall)
            }
        }
    }

    /**
     * 自动查找并关联通话录音文件（仅在通话接通时调用）
     */
    private suspend fun autoFindAndLinkCallRecord(callRecord: CallRecord) {
        println("🔍 CallRecordManager: 开始自动查找通话录音文件...")
        println("   📞 目标号码: ${callRecord.phoneNumber}")
        println("   🕐 通话时间: ${callRecord.formattedStartTime}")
        println("   📍 通话状态: ${callRecord.status}")

        try {
            // 获取应用上下文
            val context = uploadRepository?.context ?: run {
                println("❌ CallRecordManager: UploadRepository 未初始化")
                return
            }

            // 使用 AudioQueryManager 的查询逻辑
            val audioFiles = queryAudioInTargetDirs(context)

            if (audioFiles.isNotEmpty()) {
                // 按修改时间倒序排序，选择最新的文件
                val sortedFiles = audioFiles.sortedByDescending { it.dateModified }
                val latestFile = sortedFiles.first()

                println("✅ CallRecordManager: 找到 ${audioFiles.size} 个音频文件，选择最新的:")
                println("   🎵 文件名: ${latestFile.displayName}")
                println("   📁 路径: ${latestFile.filePath}")
                println("   🕐 修改时间: ${latestFile.dateModified}")
                println("   📊 文件大小: ${latestFile.size} 字节")

                // 创建 SelectedAudioFile
                val selectedAudioFile = SelectedAudioFile(
                    uri = latestFile.contentUri,
                    fileName = latestFile.displayName
                )

                // 设置选择的音频文件（这会触发上传）
                withContext(Dispatchers.Main) {
                    setSelectedAudioFile(selectedAudioFile)
                }
            } else {
                println("❌ CallRecordManager: 目标目录下没有任何音频文件")
                // 即使没有找到录音文件，也要上传通话记录
                _recentCall.value = callRecord.copy(
                    audioFileName = null,
                    audioFileUri = null
                )
                uploadCallRecord(callRecord)
            }

        } catch (e: Exception) {
            println("❌ CallRecordManager: 自动查找录音文件失败: ${e.message}")
            e.printStackTrace()
            // 即使查找失败，也要上传通话记录
            uploadCallRecord(callRecord)
        }
    }

    // 使用音频文件更新通话记录并上传
    private fun updateAndUploadCallRecord(callRecord: CallRecord, audioFile: SelectedAudioFile?) {
        // 获取音频时长
        val audioDuration = getAudioDuration(audioFile?.uri)
        // 更新通话记录
        val updatedRecord = callRecord.copy(
            audioFileName = audioFile?.fileName,
            audioFileUri = audioFile?.uri.toString(),
            duration = audioDuration
        )

        // 添加到通话记录列表
        _callRecords.value = listOf(updatedRecord) + _callRecords.value
        _recentCall.value = updatedRecord
        _uploadStatus.value = UploadStatus.UPLOADING

        println("✅ CallRecordManager: 通话记录已关联音频文件")
        println("   📞 电话号码: ${updatedRecord.phoneNumber}")
        println("   🎵 音频文件: ${updatedRecord.audioFileName}")
        println("   ⏱️ 通话时长: ${updatedRecord.formattedDuration}")
        println("   📍 通话状态: ${updatedRecord.status}")

        // 触发上传
        uploadCallRecord(updatedRecord)
    }

    private fun getAudioDuration(uri: Uri?): Long {
        if (uri == null) return 0

        return try {
            val mmr = MediaMetadataRetriever()
            mmr.setDataSource(uploadRepository?.context, uri)
            val durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
            mmr.release()

            durationStr?.toLong()?.div(1000) ?: 0L
        } catch (e: Exception) {
            0L
        }
    }

    // 通话失败记录
    fun markCallAsFailed(error: String? = null) {
        _currentCall.value?.let { current ->
            val endTime = Date()
            val duration = (endTime.time - current.startTime.time) / 1000

            val failedCall = current.copy(
                endTime = endTime,
                duration = duration,
                status = CallStatus.FAILED
            )

            _callRecords.value = listOf(failedCall) + _callRecords.value
            _currentCall.value = null

            println("❌ CallRecordManager: 通话失败 - 号码: ${failedCall.phoneNumber}, 错误: $error")

            // 通话失败时也上传记录
            uploadCallRecord(failedCall)
        }
    }

    // 上传通话记录
    private fun uploadCallRecord(callRecord: CallRecord) {
        println("📤 CallRecordManager: 开始上传通话记录...")
        println("   📞 电话号码: ${callRecord.phoneNumber}")
        println("   ⏱️ 通话时长: ${callRecord.formattedDuration}")
        println("   🎵 音频文件: ${callRecord.audioFileName ?: "无"}")
        println("   🕐 开始时间: ${callRecord.formattedStartTime}")
        println("   🕐 结束时间: ${callRecord.formattedEndTime}")
        println("   📍 通话状态: ${callRecord.status}")

        // 调用真正的上传实现
        uploadToServer(callRecord)
    }

    // 手动触发上传（用于重新上传）
    fun manuallyUploadRecentCall() {
        _recentCall.value?.let { callRecord ->
            if (!callRecord.uploaded) {
                _uploadStatus.value = UploadStatus.UPLOADING
                uploadCallRecord(callRecord)
            }
        }
    }

    // 清除最近通话记录
    fun clearRecentCall() {
        _recentCall.value = null
        _uploadStatus.value = UploadStatus.IDLE
    }

    // 真正的上传到服务器实现
    private fun uploadToServer(callRecord: CallRecord) {
        scope.launch {
            try {
                val repository = uploadRepository
                if (repository == null) {
                    println("❌ CallRecordManager: UploadRepository 未初始化，请先调用 initialize() 方法")
                    _uploadStatus.value = UploadStatus.FAILED
                    return@launch
                }

                println("🚀 CallRecordManager: 开始真实上传流程")
                println("   📍 通话状态: ${callRecord.status}")
                println("   🎵 是否有录音文件: ${callRecord.audioFileName != null}")

                // 根据通话状态决定上传方式
                val success = if (callRecord.status == CallStatus.CONNECTED && callRecord.audioFileName != null) {
                    // 已接通且有录音文件：上传完整记录（包含录音）
                    repository.uploadCallRecordWithAudio(callRecord)
                } else {
                    // 未接通或没有录音文件：只上传通话记录
                    repository.uploadCallRecordOnly(callRecord)
                }

                if (success) {
                    println("✅ CallRecordManager: 上传成功")
                    _uploadStatus.value = UploadStatus.SUCCESS
                    setSelectedAudioFile(null)

                    // 更新记录状态为已上传
                    _recentCall.value = callRecord.copy(uploaded = true, uploadTime = Date())
                    _callRecords.value = _callRecords.value.map { record ->
                        if (record.id == callRecord.id) {
                            record.copy(uploaded = true, uploadTime = Date())
                        } else {
                            record
                        }
                    }

                    // 3秒后重置上传状态
                    launch(Dispatchers.IO) {
                        kotlinx.coroutines.delay(3000)
                        _uploadStatus.value = UploadStatus.IDLE
                    }
                } else {
                    println("❌ CallRecordManager: 上传失败")
                    _uploadStatus.value = UploadStatus.FAILED
                }

            } catch (e: Exception) {
                println("❌ CallRecordManager: 上传异常: ${e.message}")
                e.printStackTrace()
                _uploadStatus.value = UploadStatus.FAILED
            }
        }
    }

    // 以下辅助方法保持不变...
    private suspend fun queryAudioInTargetDirs(context: Context): List<AudioFile> = withContext(Dispatchers.IO) {
        val audioList = mutableListOf<AudioFile>()
        val TAG = "CallRecordManager"

        // 目标目录列表
        val targetDirectories = listOf(
            "/storage/emulated/0/MIUI/sound_recorder/call_rec/", // 小米
            "/storage/emulated/0/Record/call/",                  // 华为
            "/storage/emulated/0/Sounds/CallRecord/",            // 其他华为机型
            "/storage/emulated/0/AudioRecord/",                  // 其他华为机型
            "/storage/emulated/0/Music/Sound_recorder/Phone_recorder/"
        )

        Log.d(TAG, "开始查询目标目录音频文件")

        // 首先尝试 MediaStore 查询
        val mediaStoreFiles = queryAudioInTargetDirsViaMediaStore(context, targetDirectories)
        audioList.addAll(mediaStoreFiles)
        Log.d(TAG, "MediaStore 查询结果: ${mediaStoreFiles.size} 个文件")

        // 如果 MediaStore 没有找到，尝试文件系统直接查询
        if (mediaStoreFiles.isEmpty()) {
            Log.d(TAG, "MediaStore 未找到文件，尝试文件系统查询...")
            val fileSystemFiles = queryAudioInTargetDirsViaFileSystem(context, targetDirectories)
            audioList.addAll(fileSystemFiles)
            Log.d(TAG, "文件系统查询结果: ${fileSystemFiles.size} 个文件")
        }

        Log.d(TAG, "最终查询结果: 总共找到 ${audioList.size} 个音频文件")
        return@withContext audioList
    }

    // MediaStore 查询
    private suspend fun queryAudioInTargetDirsViaMediaStore(context: Context, targetDirectories: List<String>): List<AudioFile> = withContext(Dispatchers.IO) {
        val audioList = mutableListOf<AudioFile>()
        val contentResolver = context.contentResolver
        val TAG = "CallRecordManager"

        val projection = arrayOf(
            MediaStore.Audio.Media._ID,
            MediaStore.Audio.Media.DISPLAY_NAME,
            MediaStore.Audio.Media.TITLE,
            MediaStore.Audio.Media.ARTIST,
            MediaStore.Audio.Media.ALBUM,
            MediaStore.Audio.Media.DURATION,
            MediaStore.Audio.Media.SIZE,
            MediaStore.Audio.Media.DATE_ADDED,
            MediaStore.Audio.Media.DATE_MODIFIED,
            MediaStore.Audio.Media.DATA,
            MediaStore.Audio.Media.MIME_TYPE
        )

        val sortOrder = "${MediaStore.Audio.Media.DATE_ADDED} DESC"

        // 构建目录查询条件
        val directoryConditions = targetDirectories.map {
            "${MediaStore.Audio.Media.DATA} LIKE ?"
        }
        val selection = directoryConditions.joinToString(" OR ")
        val selectionArgs = targetDirectories.map { "$it%" }.toTypedArray()

        Log.d(TAG, "MediaStore 查询条件: $selection")
        Log.d(TAG, "查询参数: ${selectionArgs.joinToString()}")

        contentResolver.query(
            MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            sortOrder
        )?.use { cursor ->
            Log.d(TAG, "MediaStore 查询结果: 找到 ${cursor.count} 条记录")

            val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)
            val displayNameColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)
            val titleColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)
            val artistColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)
            val albumColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM)
            val durationColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)
            val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE)
            val dateAddedColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATE_ADDED)
            val dateModifiedColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATE_MODIFIED)
            val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)
            val mimeTypeColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.MIME_TYPE)

            var processedCount = 0

            while (cursor.moveToNext()) {
                try {
                    val id = cursor.getLong(idColumn)
                    val displayName = cursor.getString(displayNameColumn) ?: "未知文件"
                    val title = cursor.getString(titleColumn) ?: displayName
                    val artist = cursor.getString(artistColumn) ?: "未知艺术家"
                    val album = cursor.getString(albumColumn) ?: "未知专辑"
                    val duration = cursor.getLong(durationColumn)
                    val size = cursor.getLong(sizeColumn)
                    val dateAdded = cursor.getLong(dateAddedColumn) * 1000
                    val dateModified = cursor.getLong(dateModifiedColumn) * 1000
                    val filePath = cursor.getString(dataColumn)
                    val mimeType = cursor.getString(mimeTypeColumn) ?: "unknown"

                    if (filePath != null && isInTargetDirectory(filePath, targetDirectories)) {
                        Log.d(TAG, "✅ MediaStore 找到文件: $filePath")

                        val contentUri = ContentUris.withAppendedId(
                            MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                            id
                        )

                        audioList.add(
                            AudioFile(
                                id = id,
                                displayName = displayName,
                                title = title,
                                artist = artist,
                                album = album,
                                duration = duration,
                                size = size,
                                dateAdded = dateAdded,
                                dateModified = dateModified,
                                contentUri = contentUri,
                                filePath = filePath,
                            )
                        )
                    }

                    processedCount++
                } catch (e: Exception) {
                    Log.e(TAG, "处理 MediaStore 记录时出错", e)
                }
            }
        }

        return@withContext audioList
    }

    // 辅助方法：检查文件是否在目标目录中
    private fun isInTargetDirectory(filePath: String, targetDirectories: List<String>): Boolean {
        return targetDirectories.any { filePath.startsWith(it) }
    }

    // 文件系统直接查询
    private suspend fun queryAudioInTargetDirsViaFileSystem(context: Context, targetDirectories: List<String>): List<AudioFile> = withContext(Dispatchers.IO) {
        val audioList = mutableListOf<AudioFile>()
        val TAG = "CallRecordManager"

        Log.d(TAG, "开始文件系统直接查询...")

        targetDirectories.forEach { directoryPath ->
            try {
                val directory = File(directoryPath)
                Log.d(TAG, "扫描目录: $directoryPath")

                if (directory.exists() && directory.isDirectory) {
                    val files = try {
                        directory.listFiles() ?: emptyArray()
                    } catch (e: SecurityException) {
                        Log.w(TAG, "无权限访问目录: $directoryPath")
                        emptyArray()
                    }

                    Log.d(TAG, "找到 ${files.size} 个文件/目录")

                    files.forEach { file ->
                        Log.d(TAG, "检查: ${file.name} (${if (file.isFile) "文件" else "目录"})")

                        if (file.isFile && isAudioFile(file)) {
                            Log.d(TAG, "✅ 找到音频文件: ${file.absolutePath}")

                            try {
                                audioList.add(
                                    AudioFile(
                                        id = -1,
                                        displayName = file.name,
                                        title = file.name,
                                        artist = "通话录音",
                                        album = "通话录音",
                                        duration = 0,
                                        size = file.length(),
                                        dateAdded = file.lastModified(),
                                        dateModified = file.lastModified(),
                                        contentUri = Uri.fromFile(file),
                                        filePath = file.absolutePath,
                                    )
                                )
                            } catch (e: SecurityException) {
                                Log.w(TAG, "无权限读取文件信息: ${file.absolutePath}")
                            } catch (e: Exception) {
                                Log.e(TAG, "读取文件信息失败: ${file.absolutePath}", e)
                            }
                        }
                    }
                } else {
                    Log.w(TAG, "目录不存在: $directoryPath")
                }
            } catch (e: SecurityException) {
                Log.e(TAG, "权限不足访问目录: $directoryPath")
            } catch (e: Exception) {
                Log.e(TAG, "扫描目录失败: $directoryPath", e)
            }
        }

        return@withContext audioList
    }

    // 辅助方法：判断是否为音频文件
    private fun isAudioFile(file: File): Boolean {
        val extension = file.extension.lowercase()
        val isAudio = extension in listOf("mp3", "m4a", "aac", "wav", "amr", "3gp", "ogg", "flac", "m4a", "wma")
        Log.d("CallRecordManager", "文件 ${file.name} 扩展名: $extension, 是音频文件: $isAudio")
        return isAudio
    }

    // 辅助方法：获取 MIME 类型
    private fun getMimeType(file: File): String {
        return when (file.extension.lowercase()) {
            "mp3" -> "audio/mpeg"
            "m4a" -> "audio/mp4"
            "aac" -> "audio/aac"
            "wav" -> "audio/wav"
            "amr" -> "audio/amr"
            "3gp" -> "audio/3gpp"
            "ogg" -> "audio/ogg"
            "flac" -> "audio/flac"
            else -> "audio/*"
        }
    }
}