import {
    ref,
    onUnmounted
} from 'vue'
import {
    $api
} from '../common/globalFunction'; // 你的请求封装
import config from '@/config'

// 开源
export function useAudioRecorder() {
    // --- 状态定义 ---
    const isRecording = ref(false)
    const isSocketConnected = ref(false)
    const recordingDuration = ref(0)
    const volumeLevel = ref(0) // 0-100
    const recognizedText = ref('')

    // --- 内部变量 ---
    let socketTask = null
    let durationTimer = null

    // --- APP/小程序 变量 ---
    let recorderManager = null;

    // --- H5 变量 ---
    let audioContext = null;
    let scriptProcessor = null;
    let mediaStreamSource = null;
    let h5Stream = null;

    // --- 配置项 ---
    const RECORD_CONFIG = {
        duration: 600000,
        sampleRate: 16000,
        numberOfChannels: 1,
        format: 'pcm',
        frameSize: 4096
    }

    /**
     * 获取 WebSocket 地址 (含 Token)
     */
    const getWsUrl = async () => {
        let wsUrl = config.vioceBaseURl

        // 拼接 Token
        const token = uni.getStorageSync('token') || '';
        if (token) {
            const separator = wsUrl.includes('?') ? '&' : '?';
            wsUrl = `${wsUrl}${separator}token=${encodeURIComponent(token)}`;
        }
        return wsUrl;
    }

    /**
     * 开始录音 (入口)
     */
    const startRecording = async () => {
        if (isRecording.value) return

        try {
            recognizedText.value = ''
            volumeLevel.value = 0

            // #ifdef H5
            if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
                uni.showToast({
                    title: 'H5录音需要HTTPS环境',
                    icon: 'none'
                });
                return;
            }
            // #endif

            const url = await getWsUrl()
            console.log('正在连接 ASR:', url)

            await connectSocket(url);

        } catch (err) {
            console.error('启动失败:', err);
            uni.showToast({
                title: '启动失败: ' + (err.message || ''),
                icon: 'none'
            });
            cleanup();
        }
    }

    /**
     * 连接 WebSocket
     */
    const connectSocket = (url) => {
        return new Promise((resolve, reject) => {
            socketTask = uni.connectSocket({
                url: url,
                success: () => console.log('Socket 连接请求发送'),
                fail: (err) => reject(err)
            });

            socketTask.onOpen((res) => {
                console.log('WebSocket 已连接');
                isSocketConnected.value = true;

                // #ifdef H5
                startH5Recording().then(() => resolve()).catch(err => {
                    socketTask.close();
                    reject(err);
                });
                // #endif

                // #ifndef H5
                startAppRecording();
                resolve();
                // #endif
            });

            socketTask.onMessage((res) => {
                // 接收文本结果
                if (res.data) {
                    recognizedText.value = res.data;
                }
            });

            socketTask.onError((err) => {
                console.error('Socket 错误:', err);
                isSocketConnected.value = false;
                stopRecording();
            });

            socketTask.onClose(() => {
                isSocketConnected.value = false;
                console.log('Socket 已关闭');
            });
        })
    }

    const startH5Recording = async () => {
        try {
            // 1. 获取麦克风流
            const stream = await navigator.mediaDevices.getUserMedia({
                audio: true
            });
            h5Stream = stream;

            // 2. 创建 AudioContext
            const AudioContext = window.AudioContext || window.webkitAudioContext;
            audioContext = new AudioContext({
                sampleRate: 16000
            });

            mediaStreamSource = audioContext.createMediaStreamSource(stream);
            scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1);

            scriptProcessor.onaudioprocess = (event) => {
                if (!isSocketConnected.value || !socketTask) return;

                const inputData = event.inputBuffer.getChannelData(0);

                calculateVolume(inputData, true);

                const buffer = new ArrayBuffer(inputData.length * 2);
                const view = new DataView(buffer);
                for (let i = 0; i < inputData.length; i++) {
                    let s = Math.max(-1, Math.min(1, inputData[i]));
                    view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
                }

                socketTask.send({
                    data: buffer,
                    fail: (e) => console.error('发送音频失败', e)
                });
            };

            mediaStreamSource.connect(scriptProcessor);
            scriptProcessor.connect(audioContext.destination);

            isRecording.value = true;
            recordingDuration.value = 0;
            durationTimer = setInterval(() => recordingDuration.value++, 1000);

            console.log('H5 录音已启动');

        } catch (err) {
            console.error('H5 录音启动失败:', err);
            throw err;
        }
    }

    const stopH5Resources = () => {
        if (scriptProcessor) scriptProcessor.disconnect();
        if (mediaStreamSource) mediaStreamSource.disconnect();
        if (audioContext) audioContext.close();
        if (h5Stream) h5Stream.getTracks().forEach(track => track.stop());

        scriptProcessor = null;
        mediaStreamSource = null;
        audioContext = null;
        h5Stream = null;
    }

    const startAppRecording = () => {
        recorderManager = uni.getRecorderManager();

        recorderManager.onFrameRecorded((res) => {
            const {
                frameBuffer
            } = res;

            calculateVolume(frameBuffer, false);

            if (isSocketConnected.value && socketTask) {
                socketTask.send({
                    data: frameBuffer
                });
            }
        });

        recorderManager.onStart(() => {
            console.log('APP 录音已开始');
            isRecording.value = true;
            recordingDuration.value = 0;
            durationTimer = setInterval(() => recordingDuration.value++, 1000);
        });

        recorderManager.onError((err) => {
            console.error('APP 录音报错:', err);
            cleanup();
        });

        recorderManager.start(RECORD_CONFIG);
    }
    const stopHardwareResource = () => {
        // APP/小程序停止
        if (recorderManager) {
            recorderManager.stop();
        }

        // H5停止
        // #ifdef H5
        if (scriptProcessor) scriptProcessor.disconnect();
        if (mediaStreamSource) mediaStreamSource.disconnect();
        if (audioContext) audioContext.close();
        if (h5Stream) h5Stream.getTracks().forEach(track => track.stop());

        scriptProcessor = null;
        mediaStreamSource = null;
        audioContext = null;
        h5Stream = null;
        // #endif
    }

    /**
     * 停止录音 (通用)
     */
    const stopRecording = () => {
        // 停止 APP 录音
        if (recorderManager) {
            recorderManager.stop();
        }

        // 停止 H5 录音资源
        // #ifdef H5
        stopH5Resources();
        // #endif

        // 关闭 Socket
        if (socketTask) {
            socketTask.close();
        }

        cleanup();
    }

    const cancelRecording = () => {
        if (!isRecording.value) return;

        console.log('取消录音 - 丢弃结果');

        // 1. 停止硬件录音
        stopHardwareResource();

        // 2. 强制关闭 Socket
        if (socketTask) {
            socketTask.close();
        }

        // 3. 关键：清空已识别的文本
        recognizedText.value = '';

        // 4. 清理资源
        cleanup();
    }

    /**
     * 清理状态
     */
    const cleanup = () => {
        clearInterval(durationTimer);
        isRecording.value = false;
        isSocketConnected.value = false;
        socketTask = null;
        recorderManager = null;
        volumeLevel.value = 0;
    }

    /**
     * 计算音量 (兼容 Float32 和 Int16/ArrayBuffer)
     */
    const calculateVolume = (data, isFloat32) => {
        let sum = 0;
        let length = 0;

        if (isFloat32) {
            length = data.length;
            for (let i = 0; i < length; i += 10) {
                sum += Math.abs(data[i]);
            }
            volumeLevel.value = Math.min(100, Math.floor((sum / (length / 10)) * 100 * 3));
        } else {
            const int16Data = new Int16Array(data);
            length = int16Data.length;
            for (let i = 0; i < length; i += 10) {
                sum += Math.abs(int16Data[i]);
            }
            const avg = sum / (length / 10);
            volumeLevel.value = Math.min(100, Math.floor((avg / 10000) * 100));
        }
    }

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

    return {
        isRecording,
        isSocketConnected,
        recordingDuration,
        volumeLevel,
        recognizedText,
        startRecording,
        stopRecording,
        cancelRecording
    }
}