import {
    ref,
    onUnmounted
} from 'vue'
import {
    $api,
} from '@/common/globalFunction';

import config from '@/config'

export function useAudioRecorder() {
    const isRecording = ref(false)
    const isStopping = ref(false)
    const isSocketConnected = ref(false)
    const recordingDuration = ref(0)

    const audioDataForDisplay = ref(new Array(16).fill(0))
    const volumeLevel = ref(0)

    const recognizedText = ref('')
    const lastFinalText = ref('')
    const isRecognizing = ref(false) // 识别状态，暴露给外部

    let audioStream = null
    let audioContext = null
    let audioInput = null
    let scriptProcessor = null
    let websocket = null
    let durationTimer = null

    const generateUUID = () => {
        return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11)
            .replace(/[018]/g, c =>
                (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
            ).replace(/-/g, '')
    }

    const fetchWsUrl = async () => {
        const res = await $api.createRequest('/app/speech/getToken')
        if (res.code !== 200) throw new Error('无法获取语音识别 wsUrl')
        const wsUrl = res.msg
        return wsUrl
    }

    function extractWsParams(wsUrl) {
        const url = new URL(wsUrl)
        const appkey = url.searchParams.get('appkey')
        const token = url.searchParams.get('token')
        return {
            appkey,
            token
        }
    }


    const connectWebSocket = async () => {
        const wsUrl = await fetchWsUrl()
        const {
            appkey,
            token
        } = extractWsParams(wsUrl)
        return new Promise((resolve, reject) => {
            websocket = new WebSocket(wsUrl)
            websocket.binaryType = 'arraybuffer'

            websocket.onopen = () => {
                isSocketConnected.value = true

                // 发送 StartTranscription 消息（参考 demo.html）
                const startTranscriptionMessage = {
                    header: {
                        appkey: appkey, // 不影响使用，可留空或由 wsUrl 带入
                        namespace: 'SpeechTranscriber',
                        name: 'StartTranscription',
                        task_id: generateUUID(),
                        message_id: generateUUID()
                    },
                    payload: {
                        format: 'pcm',
                        sample_rate: 16000,
                        enable_intermediate_result: true,
                        enable_punctuation_prediction: true,
                        enable_inverse_text_normalization: true
                    }
                }
                websocket.send(JSON.stringify(startTranscriptionMessage))
                resolve()
            }

            websocket.onerror = (e) => {
                isSocketConnected.value = false
                reject(e)
            }

            websocket.onclose = () => {
                isSocketConnected.value = false
            }

            websocket.onmessage = (e) => {
                const msg = JSON.parse(e.data)
                const name = msg?.header?.name
                const payload = msg?.payload

                switch (name) {
                    case 'TranscriptionResultChanged': {
                        // 中间识别文本（可选：使用 stash_result.unfixedText 更精确）
                        const text = payload?.unfixed_result || payload?.result || ''
                        lastFinalText.value = text
                        break
                    }
                    case 'SentenceBegin': {
                        // 可选：开始新的一句，重置状态
                        // console.log('开始新的句子识别')
                        break
                    }
                    case 'SentenceEnd': {
                        const text = payload?.result || ''
                        const confidence = payload?.confidence || 0
                        if (text && confidence > 0.5) {
                            recognizedText.value += text
                            lastFinalText.value = ''
                            // console.log('识别完成:', {
                            //     text,
                            //     confidence
                            // })
                        }
                        break
                    }
                    case 'TranscriptionStarted': {
                        // console.log('识别任务已开始')
                        break
                    }
                    case 'TranscriptionCompleted': {
                        lastFinalText.value = ''
                        isRecognizing.value = false // 识别完成，重置状态
                        // console.log('识别全部完成')
                        cleanup()
                        break
                    }
                    case 'TaskFailed': {
                        console.error('识别失败:', msg?.header?.status_text)
                        isRecognizing.value = false // 识别失败，重置状态
                        cleanup()
                        break
                    }
                    default:
                        console.log('未知消息类型:', name, msg)
                        break
                }
            }
        })
    }

    const startRecording = async () => {
        if (isRecording.value) return
        
        // #ifdef MP-WEIXIN
        try {
            recognizedText.value = ''
            lastFinalText.value = ''
            // 开始录音时不设置isRecognizing为true，只有在停止录音后才保持isRecognizing为true
            
            const recorderManager = uni.getRecorderManager()
            
            // 监听录音完成事件
            recorderManager.onStop(async (res) => {
                console.log('小程序录音完成:', res)
                try {
                    // 停止录音后设置isRecognizing为true，显示loading
                    isRecognizing.value = true
                    
                    // 打印请求配置，便于调试
                    console.log('准备上传语音识别请求配置:', {
                        url: config.vioceBaseURl,
                        name: 'file',
                        method: 'POST',
                        fileType: 'audio',
                        filePath: res.tempFilePath
                    })
                    
                    // 上传录音文件到服务器进行语音识别
                    const uploadResult = await uni.uploadFile({
                        url: config.vioceBaseURl,
                        filePath: res.tempFilePath,
                        name: 'file',
                        fileType: 'audio',
                        method: 'POST' // 显式设置为POST请求
                    })
                    
                    console.log('语音识别上传结果:', uploadResult)
                    
                    if (uploadResult.statusCode === 200) {
                        try {
                            const result = JSON.parse(uploadResult.data)
                            console.log('语音识别结果:', result)
                            if (result.code === 200 && result.data) {
                                recognizedText.value = result.data
                                console.log('语音识别成功，识别结果:', recognizedText.value)
                                // 语音识别成功后，自动发送消息
                                // 这里需要触发一个事件，让父组件知道识别成功
                                // 或者直接调用发送消息的方法
                                isRecognizing.value = false // 识别成功，重置状态
                            } else {
                                console.error('语音识别返回错误:', result.message || '未知错误')
                                $api.msg('语音识别失败，请重试')
                                isRecognizing.value = false // 识别失败，重置状态
                            }
                        } catch (parseErr) {
                            console.error('语音识别结果解析失败:', parseErr)
                            $api.msg('语音识别失败，请重试')
                            isRecognizing.value = false // 解析失败，重置状态
                        }
                    } else {
                        console.error('语音识别请求失败，状态码:', uploadResult.statusCode)
                        $api.msg('语音识别失败，请重试')
                        isRecognizing.value = false // 请求失败，重置状态
                    }
                } catch (err) {
                    console.error('语音识别上传失败:', err)
                    $api.msg('语音识别失败，请重试')
                    isRecognizing.value = false // 上传失败，重置状态
                }
            })
            
            // 监听录音错误事件
            recorderManager.onError((err) => {
                console.error('小程序录音错误:', err)
                $api.msg('录音失败，请重试');
                cleanup()
            })
            
            // 微信小程序录音API
            await recorderManager.start({
                duration: 60000, // 最长录音60秒
                sampleRate: 16000,
                numberOfChannels: 1,
                encodeBitRate: 96000,
                format: 'mp3'
            })
            
            isRecording.value = true
            recordingDuration.value = 0
            durationTimer = setInterval(() => recordingDuration.value++, 1000)
            
            // 监听录音事件（可选）
            recorderManager.onFrameRecorded((res) => {
                // 更新音量显示
                volumeLevel.value = res.volume || 0
                audioDataForDisplay.value = Array(16).fill(volumeLevel.value)
            })
        } catch (err) {
            console.error('小程序录音启动失败:', err)
            $api.msg('录音启动失败，请重试');
            cleanup()
        }
        return;
        // #endif
        
        // #ifdef H5
        try {
            if (typeof navigator === 'undefined' || !navigator.mediaDevices) {
                $api.msg('当前环境不支持录音功能');
                return;
            }
            
            recognizedText.value = ''
            lastFinalText.value = ''
            // 开始录音时不设置isRecognizing为true，只有在停止录音后才保持isRecognizing为true
            await connectWebSocket()

            audioStream = await navigator.mediaDevices.getUserMedia({
                audio: true
            })
            audioContext = new(window.AudioContext || window.webkitAudioContext)({
                sampleRate: 16000
            })
            audioInput = audioContext.createMediaStreamSource(audioStream)
            scriptProcessor = audioContext.createScriptProcessor(2048, 1, 1)

            scriptProcessor.onaudioprocess = (event) => {
                const input = event.inputBuffer.getChannelData(0)
                const pcm = new Int16Array(input.length)
                let sum = 0
                for (let i = 0; i < input.length; ++i) {
                    const s = Math.max(-1, Math.min(1, input[i]))
                    pcm[i] = s * 0x7FFF
                    sum += s * s
                }

                volumeLevel.value = Math.sqrt(sum / input.length)
                audioDataForDisplay.value = Array(16).fill(volumeLevel.value)

                if (websocket?.readyState === WebSocket.OPEN) {
                    websocket.send(pcm.buffer)
                }
            }

            audioInput.connect(scriptProcessor)
            scriptProcessor.connect(audioContext.destination)

            isRecording.value = true
            recordingDuration.value = 0
            durationTimer = setInterval(() => recordingDuration.value++, 1000)
        } catch (err) {
            console.error('启动失败:', err)
            isRecognizing.value = false // 启动失败，重置状态
            cleanup()
        }
        // #endif
    }

    const stopRecording = () => {
        if (!isRecording.value || isStopping.value) return
        isStopping.value = true

        // #ifdef MP-WEIXIN
        uni.getRecorderManager().stop()
        // 小程序中录音停止后会触发onStop事件，在onStop事件中处理识别结果和状态重置
        // #endif
        
        // #ifdef H5
        if (websocket?.readyState === WebSocket.OPEN) {
            websocket.send(JSON.stringify({
                header: {
                    namespace: 'SpeechTranscriber',
                    name: 'StopTranscription',
                    message_id: generateUUID()
                }
            }))
            // H5中不立即调用cleanup，等待识别完成
        }
        // #endif

        // 只清理录音相关资源，不重置识别状态
        clearInterval(durationTimer)
        audioStream?.getTracks().forEach(track => track.stop())
        audioContext?.close()
        audioStream = null
        audioContext = null
        audioInput = null
        scriptProcessor = null
        
        isRecording.value = false
        isSocketConnected.value = false
        isStopping.value = false
    }

    const cancelRecording = () => {
        if (!isRecording.value || isStopping.value) return
        isStopping.value = true
        
        // #ifdef MP-WEIXIN
        uni.getRecorderManager().stop()
        // #endif
        
        // #ifdef H5
        websocket?.close()
        // #endif
        
        // 取消录音时重置所有状态
        cleanup()
        isRecognizing.value = false
        isStopping.value = false
    }

    const cleanup = () => {
        clearInterval(durationTimer)

        scriptProcessor?.disconnect()
        audioInput?.disconnect()
        audioStream?.getTracks().forEach(track => track.stop())
        audioContext?.close()

        audioStream = null
        audioContext = null
        audioInput = null
        scriptProcessor = null
        websocket = null

        isRecording.value = false
        isSocketConnected.value = false
        isRecognizing.value = false // 停止录音，重置识别状态
    }

    onUnmounted(() => {
        if (isRecording.value) stopRecording()
    })

    const reset = () => {
        cleanup()
    }

    return {
        isRecording,
        isStopping,
        isSocketConnected,
        isRecognizing,
        recordingDuration,
        audioDataForDisplay,
        volumeLevel,
        recognizedText,
        lastFinalText,
        startRecording,
        stopRecording,
        cancelRecording,
        reset
    }
}