import {
    ref,
    onUnmounted,
    onMounted
} from 'vue'
// 如果是 uni-app 环境，保留这些导入；如果是纯 Web Vue3，可以移除
import {
    onHide,
    onUnload
} from '@dcloudio/uni-app'
import config from '@/config'

/**
 * Piper TTS 播放钩子 (WebSocket MSE 流式版 - 含 cancelAudio)
 * 依赖: 后端必须去除 MP3 ID3 标签 (-map_metadata -1)
 */
export function useTTSPlayer() {
    // 状态管理
    const isSpeaking = ref(false)
    const isPaused = ref(false)
    const isLoading = ref(false)

    // 核心对象
    let audio = null
    let mediaSource = null
    let sourceBuffer = null
    let ws = null

    // 缓冲队列管理
    let bufferQueue = []
    let isAppending = false
    let isStreamEnded = false

    // 初始化 Audio 监听器 (只运行一次)
    const initAudioElement = () => {
        if (!audio && typeof window !== 'undefined') {
            audio = new Audio()

            // 错误监听
            audio.addEventListener('error', (e) => {
                // 如果是手动停止导致的 error (src 被置空)，忽略
                if (!audio.src) return
                console.error('Audio Player Error:', e)
                resetState()
            })

            // 播放结束监听
            audio.addEventListener('ended', () => {
                resetState()
            })
        }
    }

    /**
     * 核心朗读方法 (WebSocket)
     * @param {string} text - 要朗读的文本
     */
    const speak = async (text) => {
        if (!text) return

        // 1. 提取文本
        const processedText = extractSpeechText(text)
        if (!processedText) return

        // 2. 彻底清理旧状态
        cancelAudio()
        initAudioElement()

        isLoading.value = true
        isSpeaking.value = true
        isPaused.value = false
        isStreamEnded = false

        // 3. 检查环境
        if (!window.MediaSource || !window.WebSocket) {
            console.error('当前环境不支持 MediaSource 或 WebSocket')
            resetState()
            return
        }

        try {
            // 4. 初始化 MSE
            mediaSource = new MediaSource()
            // 绑定 MSE 到 Audio
            audio.src = URL.createObjectURL(mediaSource)

            // 监听 MSE 打开事件
            mediaSource.addEventListener('sourceopen', () => {
                // 防止多次触发
                if (mediaSource.sourceBuffers.length > 0) return
                startWebSocketStream(processedText)
            })

            // 尝试播放 (处理浏览器自动播放策略)
            const playPromise = audio.play()
            if (playPromise !== undefined) {
                playPromise.catch(e => {
                    console.warn('自动播放被拦截 (需用户交互):', e)
                    // 保持 isSpeaking 为 true，UI 显示播放按钮，用户点击后调用 resume() 即可
                })
            }

        } catch (err) {
            console.error('TTS Initialization Failed:', err)
            cancelAudio()
        }
    }

    // 启动 WebSocket 流程
    const startWebSocketStream = (text) => {
        const mime = 'audio/mpeg'

        // 4.1 创建 SourceBuffer
        try {
            sourceBuffer = mediaSource.addSourceBuffer(mime)
            sourceBuffer.addEventListener('updateend', () => {
                isAppending = false
                processQueue()
            })
        } catch (e) {
            console.error('SourceBuffer Create Failed:', e)
            return
        }

        // 4.2 计算 WebSocket 地址
        let baseUrl = config.speechSynthesis2 || ''
        baseUrl = baseUrl.replace(/\/$/, '')
        const wsUrl = baseUrl.replace(/^http/, 'ws') + '/ws/synthesize'

        // 4.3 建立连接
        ws = new WebSocket(wsUrl)
        ws.binaryType = 'arraybuffer' // 关键

        ws.onopen = () => {
            // console.log('WS Open')
            ws.send(JSON.stringify({
                text: text,
                speaker_id: 0,
                length_scale: 1.0,
                noise_scale: 0.667
            }))
            isLoading.value = false
        }

        ws.onmessage = (event) => {
            if (event.data instanceof ArrayBuffer) {
                bufferQueue.push(event.data)
                processQueue()
            }
        }

        ws.onerror = (e) => {
            console.error('WS Error:', e)
            cancelAudio()
        }

        ws.onclose = () => {
            // console.log('WS Closed')
            isStreamEnded = true
            // 检查是否需要结束 MSE 流
            checkEndOfStream()
        }
    }

    // 处理缓冲队列
    const processQueue = () => {
        if (!sourceBuffer || sourceBuffer.updating || bufferQueue.length === 0) {
            // 如果队列空了，且流已结束，尝试结束 MSE
            if (bufferQueue.length === 0 && isStreamEnded && !sourceBuffer.updating) {
                checkEndOfStream()
            }
            return
        }

        isAppending = true
        const chunk = bufferQueue.shift()

        try {
            sourceBuffer.appendBuffer(chunk)
        } catch (e) {
            // console.error('AppendBuffer Error:', e)
            isAppending = false
        }
    }

    // 结束 MSE 流
    const checkEndOfStream = () => {
        if (mediaSource && mediaSource.readyState === 'open' && bufferQueue.length === 0 && !sourceBuffer
            ?.updating) {
            try {
                mediaSource.endOfStream()
            } catch (e) {}
        }
    }

    const pause = () => {
        if (audio && !audio.paused) {
            audio.pause()
            isPaused.value = true
            isSpeaking.value = false
        }
    }

    const resume = () => {
        if (audio && audio.paused) {
            audio.play()
            isPaused.value = false
            isSpeaking.value = true
        }
    }

    // === 新增/核心方法：取消并停止 ===
    const cancelAudio = () => {
        // 1. 断开 WebSocket (停止数据接收)
        if (ws) {
            // 移除监听器防止报错
            ws.onclose = null
            ws.onerror = null
            ws.onmessage = null
            ws.close()
            ws = null
        }

        // 2. 停止音频播放
        if (audio) {
            audio.pause()
            // 释放 Blob URL 内存
            if (audio.src) {
                URL.revokeObjectURL(audio.src)
                audio.removeAttribute('src')
            }
            audio.currentTime = 0
        }

        // 3. 清理 MSE 对象
        if (mediaSource) {
            try {
                if (mediaSource.readyState === 'open') {
                    mediaSource.endOfStream()
                }
            } catch (e) {}
            mediaSource = null
        }

        sourceBuffer = null
        bufferQueue = []
        isAppending = false
        isStreamEnded = false

        // 4. 重置 UI 状态
        resetState()
    }

    // 只是重置 UI 变量的辅助函数
    const resetState = () => {
        isSpeaking.value = false
        isPaused.value = false
        isLoading.value = false
    }

    // 别名 stop -> cancelAudio (保持兼容性)
    const stop = cancelAudio

    // === 生命周期 ===
    onMounted(() => {
        initAudioElement()
    })

    onUnmounted(() => {
        cancelAudio()
        audio = null
    })

    if (typeof onHide === 'function') onHide(cancelAudio)
    if (typeof onUnload === 'function') onUnload(cancelAudio)

    return {
        speak,
        pause,
        resume,
        stop,
        cancelAudio, // 新增导出
        isSpeaking,
        isPaused,
        isLoading
    }
}

/**
 * 提取文本逻辑
 */
function extractSpeechText(markdown) {
    if (!markdown || markdown.indexOf('job-json') === -1) {
        return markdown;
    }

    const jobRegex = /``` job-json\s*({[\s\S]*?})\s*```/g;
    const jobs = [];
    let match;
    let lastJobEndIndex = 0;
    let firstJobStartIndex = -1;

    while ((match = jobRegex.exec(markdown)) !== null) {
        const jobStr = match[1];
        try {
            const job = JSON.parse(jobStr);
            jobs.push(job);
            if (firstJobStartIndex === -1) {
                firstJobStartIndex = match.index;
            }
            lastJobEndIndex = jobRegex.lastIndex;
        } catch (e) {
            console.warn('JSON 解析失败', e);
        }
    }

    const guideText = firstJobStartIndex > 0 ?
        markdown.slice(0, firstJobStartIndex).trim() : '';

    const endingText = lastJobEndIndex < markdown.length ?
        markdown.slice(lastJobEndIndex).trim() : '';

    const jobTexts = jobs.map((job, index) => {
        return `第 ${index + 1} 个岗位，岗位名称是：${job.jobTitle}，公司是：${job.companyName}，薪资：${job.salary}，地点：${job.location}，学历要求：${job.education}，经验要求：${job.experience}。`;
    });

    const finalTextParts = [];
    if (guideText) finalTextParts.push(guideText);
    finalTextParts.push(...jobTexts);
    if (endingText) finalTextParts.push(endingText);

    return finalTextParts.join('\n');
}