import { ref, onUnmounted } from 'vue';
import { io, Socket } from 'socket.io-client';
import { config } from '/@/config';
import { useBase } from '/$/base';
import type { VoiceMessage } from '../types/index.d';

type VoiceState = 'idle' | 'connecting' | 'active' | 'disconnecting';

/**
 * 实时语音交互 Composable
 * Socket.io 连接 + 麦克风录音(PCM 16kHz/int16/mono) + TTS 音频播放 + 状态机 + 语音消息管理
 */
export function useRealtimeVoice() {
	const { user } = useBase();

	const state = ref<VoiceState>('idle');
	const messages = ref<VoiceMessage[]>([]);
	const isMuted = ref(false);

	let socket: Socket | null = null;
	let audioContext: AudioContext | null = null;
	let mediaStream: MediaStream | null = null;
	let scriptProcessor: ScriptProcessorNode | null = null;
	let mediaSourceNode: MediaStreamAudioSourceNode | null = null;

	// TTS 流式播放（PCM AudioWorklet）
	let playbackContext: AudioContext | null = null;
	let workletNode: AudioWorkletNode | null = null;
	let workletReady = false;

	// 当前正在构建的 ASR 消息 ID
	let currentAsrMsgId: string | null = null;
	// 当前正在构建的 Chat 消息 ID
	let currentChatMsgId: string | null = null;

	// 通话计时
	let callStartTime = 0;
	const callDuration = ref(0);
	let durationTimer: ReturnType<typeof setInterval> | null = null;

	function genId(): string {
		return Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
	}

	/** 启动语音会话 */
	async function connect(options?: {
		sessionId?: string;
		model?: string;
		systemPrompt?: string;
		voiceType?: string;
	}) {
		if (state.value !== 'idle') return;
		state.value = 'connecting';
		messages.value = [];
		currentAsrMsgId = null;
		currentChatMsgId = null;

		try {
			// 1. 获取麦克风权限
			mediaStream = await navigator.mediaDevices.getUserMedia({
				audio: {
					sampleRate: 16000,
					channelCount: 1,
					echoCancellation: true,
					noiseSuppression: true
				}
			});

			// 2. 创建 AudioContext 用于录音
			audioContext = new AudioContext({ sampleRate: 16000 });
			mediaSourceNode = audioContext.createMediaStreamSource(mediaStream);
			scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1);

			scriptProcessor.onaudioprocess = (e) => {
				if (state.value !== 'active' || isMuted.value || !socket?.connected) return;
				const float32 = e.inputBuffer.getChannelData(0);
				const int16 = float32ToInt16(float32);
				socket.emit('audio', int16.buffer);
			};

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

			// 3. 创建播放用 AudioContext（使用系统默认采样率，Worklet 内部做 24kHz→系统采样率的重采样）
			playbackContext = new AudioContext();
			await playbackContext.audioWorklet.addModule('/pcm-playback-processor.js');
			workletNode = new AudioWorkletNode(playbackContext, 'pcm-playback-processor');
			workletNode.connect(playbackContext.destination);
			workletReady = true;

			// 4. 建立 Socket.io 连接（直接连后端，不走 Vite 代理）
			const wsUrl = (config as any).host || 'http://127.0.0.1:8001';
			console.log('[realtime-voice] 连接地址:', wsUrl);
			socket = io(`${wsUrl}/realtime-voice`, {
				auth: { token: user.token, isAdmin: true },
				transports: ['websocket']
			});

			socket.on('connect', () => {
				console.log('[realtime-voice] Socket.io 已连接，发送 start 事件');
				socket!.emit('start', {
					sessionId: options?.sessionId || genId(),
					model: options?.model,
					systemPrompt: options?.systemPrompt,
					voiceType: options?.voiceType
				});
			});

			socket.on('session_ready', () => {
				console.log('[realtime-voice] 会话已就绪');
				state.value = 'active';
				callStartTime = Date.now();
				durationTimer = setInterval(() => {
					callDuration.value = Math.floor((Date.now() - callStartTime) / 1000);
				}, 1000);
			});

			socket.on('asr_info', () => {
				// ASR 首字检测 - 打断当前 TTS 播放
				stopPlayback();
			});

			socket.on('asr_result', (data: { text: string; definite: boolean }) => {
				if (!data.text) return;
				if (!data.definite) {
					if (!currentAsrMsgId) {
						currentAsrMsgId = genId();
						messages.value.push({
							id: currentAsrMsgId,
							role: 'user',
							text: data.text,
							isPartial: true,
							timestamp: Date.now()
						});
					} else {
						const msg = messages.value.find(m => m.id === currentAsrMsgId);
						if (msg) msg.text = data.text;
					}
				} else {
					if (currentAsrMsgId) {
						const msg = messages.value.find(m => m.id === currentAsrMsgId);
						if (msg) {
							msg.text = data.text;
							msg.isPartial = false;
						}
					} else {
						messages.value.push({
							id: genId(),
							role: 'user',
							text: data.text,
							isPartial: false,
							timestamp: Date.now()
						});
					}
					currentAsrMsgId = null;
				}
			});

			socket.on('asr_ended', () => {
				if (currentAsrMsgId) {
					const msg = messages.value.find(m => m.id === currentAsrMsgId);
					if (msg) msg.isPartial = false;
					currentAsrMsgId = null;
				}
			});

			socket.on('chat_response', (data: { text: string }) => {
				if (!data.text) return;
				if (!currentChatMsgId) {
					currentChatMsgId = genId();
					messages.value.push({
						id: currentChatMsgId,
						role: 'assistant',
						text: data.text,
						isPartial: true,
						timestamp: Date.now()
					});
				} else {
					const msg = messages.value.find(m => m.id === currentChatMsgId);
					if (msg) msg.text += data.text;
				}
			});

			socket.on('chat_ended', () => {
				if (currentChatMsgId) {
					const msg = messages.value.find(m => m.id === currentChatMsgId);
					if (msg) msg.isPartial = false;
					currentChatMsgId = null;
				}
			});

			// TTS 音频：收到即推送给 AudioWorklet 流式播放
			socket.on('tts_sentence_start', () => {
				// 句子开始，无需缓冲操作
			});

			socket.on('tts_audio', (data: ArrayBuffer | Uint8Array) => {
				if (!workletReady || !workletNode) return;
				// 确保 AudioContext 处于运行状态（浏览器自动暂停策略）
				if (playbackContext?.state === 'suspended') {
					playbackContext.resume();
				}
				// Socket.io 传输 Buffer 后前端可能收到 ArrayBuffer 或 Uint8Array
				// 统一转为 ArrayBuffer 再传给 Worklet，确保 Int16Array 视图对齐正确
				let ab: ArrayBuffer;
				if (data instanceof ArrayBuffer) {
					ab = data;
				} else {
					// Uint8Array: 需要用 slice 拷贝出独立的 ArrayBuffer（避免 offset 问题）
					ab = data.buffer.byteLength === data.byteLength
						? data.buffer
						: data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
				}
				workletNode.port.postMessage({ type: 'pcm', buffer: ab }, [ab]);
			});

			socket.on('tts_sentence_end', () => {
				// 句子结束，流式播放无需额外操作
			});

			socket.on('tts_ended', () => {
				// 一轮 TTS 结束，流式播放无需额外操作
			});

			socket.on('error', (data: { message: string }) => {
				console.error('[realtime-voice] 错误:', data.message);
				messages.value.push({
					id: genId(),
					role: 'assistant',
					text: `[错误] ${data.message}`,
					timestamp: Date.now()
				});
			});

			socket.on('session_stopped', () => cleanupInternal());
			socket.on('session_closed', () => cleanupInternal());
			socket.on('disconnect', () => {
				if (state.value === 'active') cleanupInternal();
			});
			socket.on('connect_error', (err) => {
				console.error('[realtime-voice] 连接失败:', err.message, err);
				cleanupInternal();
			});

		} catch (err: any) {
			console.error('[realtime-voice] 启动失败:', err);
			cleanupInternal();
			throw err;
		}
	}

	/** 停止语音会话 */
	function disconnect() {
		if (state.value === 'idle') return;
		state.value = 'disconnecting';
		if (socket?.connected) {
			socket.emit('stop');
		}
		setTimeout(() => cleanupInternal(), 500);
	}

	/** 切换静音 */
	function toggleMute() {
		isMuted.value = !isMuted.value;
	}

	/** Float32 → Int16 PCM 转换 */
	function float32ToInt16(float32: Float32Array): Int16Array {
		const int16 = new Int16Array(float32.length);
		for (let i = 0; i < float32.length; i++) {
			const s = Math.max(-1, Math.min(1, float32[i]));
			int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
		}
		return int16;
	}

	/** 停止播放（用于 ASR 打断） */
	function stopPlayback() {
		if (workletNode) {
			workletNode.port.postMessage({ type: 'clear' });
		}
	}

	/** 内部清理 */
	function cleanupInternal() {
		state.value = 'idle';
		callDuration.value = 0;

		if (durationTimer) {
			clearInterval(durationTimer);
			durationTimer = null;
		}
		if (scriptProcessor) {
			scriptProcessor.disconnect();
			scriptProcessor = null;
		}
		if (mediaSourceNode) {
			mediaSourceNode.disconnect();
			mediaSourceNode = null;
		}
		if (audioContext) {
			audioContext.close().catch(() => {});
			audioContext = null;
		}
		if (mediaStream) {
			mediaStream.getTracks().forEach(t => t.stop());
			mediaStream = null;
		}
		if (workletNode) {
			workletNode.port.postMessage({ type: 'stop' });
			workletNode.disconnect();
			workletNode = null;
			workletReady = false;
		}
		if (playbackContext) {
			playbackContext.close().catch(() => {});
			playbackContext = null;
		}
		if (socket) {
			socket.removeAllListeners();
			socket.disconnect();
			socket = null;
		}
	}

	onUnmounted(() => cleanupInternal());

	return {
		state,
		messages,
		connect,
		disconnect,
		isMuted,
		toggleMute,
		callDuration
	};
}
