import { useState, useRef } from 'react' import { Audio } from 'expo-av' import { getToken } from '@/lib/api' import { ENDPOINTS } from '@/lib/config' export type AudioState = 'idle' | 'recording' | 'processing' | 'error' export function useAudioRecorder(onTranscript: (text: string) => void) { const [state, setState] = useState('idle') const [errorMsg, setErrorMsg] = useState(null) const recordingRef = useRef(null) const startRecording = async () => { setErrorMsg(null) try { // Demande de permission const { granted } = await Audio.requestPermissionsAsync() if (!granted) { setErrorMsg('Permission micro refusée') setState('error') setTimeout(() => setState('idle'), 3000) return } await Audio.setAudioModeAsync({ allowsRecordingIOS: true, playsInSilentModeIOS: true, }) const { recording } = await Audio.Recording.createAsync( Audio.RecordingOptionsPresets.HIGH_QUALITY ) recordingRef.current = recording setState('recording') } catch (e: any) { setErrorMsg(e.message ?? 'Impossible de démarrer le micro') setState('error') setTimeout(() => setState('idle'), 3000) } } const stopAndTranscribe = async () => { const recording = recordingRef.current if (!recording) { setState('idle'); return } setState('processing') recordingRef.current = null try { // Sauvegarder l'URI AVANT d'unload const uri = recording.getURI() await recording.stopAndUnloadAsync() // Rétablir le mode audio normal await Audio.setAudioModeAsync({ allowsRecordingIOS: false }) if (!uri) throw new Error('Fichier audio vide') const token = await getToken() // FormData RN : objet {uri, name, type} const form = new FormData() form.append('audio', { uri, name: 'audio.m4a', type: 'audio/m4a' } as any) const res = await fetch(ENDPOINTS.aiTranscribe, { method: 'POST', headers: { Authorization: `Bearer ${token ?? ''}` }, body: form, }) if (!res.ok) { const d = await res.json().catch(() => ({})) throw new Error(d.error ?? `Erreur ${res.status}`) } const { text } = await res.json() if (text?.trim()) onTranscript(text.trim()) setState('idle') } catch (e: any) { setErrorMsg(e.message ?? 'Erreur transcription') setState('error') setTimeout(() => { setState('idle'); setErrorMsg(null) }, 4000) } } const cancelRecording = async () => { const recording = recordingRef.current recordingRef.current = null if (recording) { try { await recording.stopAndUnloadAsync() await Audio.setAudioModeAsync({ allowsRecordingIOS: false }) } catch {} } setState('idle') setErrorMsg(null) } return { state, errorMsg, startRecording, stopAndTranscribe, cancelRecording } }