import { AppState, Platform } from 'react-native';
import type { Room } from 'livekit-client';
import { getCallTokenCached } from './service';

// Rooms pré-chauffées pendant la sonnerie (prepareConnection = DNS/TLS/ICE établis d'avance) → consommées par
// CallScreen au décroché pour une connexion « à chaud » (le 1ᵉʳ appel n'est plus à froid).
//
// ⚠ IMPORTANT : ce module est dans le graphe de DÉMARRAGE (useVoipCalls, incoming-call). Il ne doit JAMAIS importer
// `livekit-client` au niveau module (WebRTC lourd, avant registerGlobals, parfois en headless → app figée au splash).
// → import de TYPE uniquement ci-dessus, et chargement du SDK en DIFFÉRÉ (dynamic import) seulement dans prewarmCall.
const warmRooms = new Map<string, Room>();

/**
 * Pré-chauffe un appel entrant PENDANT la sonnerie : préfetch du jeton, puis — SI l'app est au premier plan — crée une
 * Room et lance `prepareConnection` (aucun micro, aucune publication ; juste l'établissement de la connexion). Au
 * décroché, la poignée de main LiveKit part instantanément. Best-effort : n'émet jamais d'erreur (repli : CallScreen
 * crée sa propre Room). Premier plan uniquement → évite un contexte headless (Android FCM) où les globals WebRTC / la
 * Room ne sont pas viables. `livekit-client` chargé en différé (après registerGlobals) → jamais au démarrage.
 */
export function prewarmCall(callId: string): void {
    if (!callId) return;
    void (async () => {
        let t: Awaited<ReturnType<typeof getCallTokenCached>>;
        try {
            t = await getCallTokenCached(callId);
        } catch {
            return; // pas de jeton (réseau/refusé) → rien à pré-chauffer
        }
        // iOS : après un push VoIP, l'app s'exécute réellement (JS booté, registerGlobals faits, CallKit actif) MÊME en
        // arrière-plan → on préchauffe la connexion aussi en background (c'est justement le cas iOS courant). Android en
        // arrière-plan = contexte headless (FCM) où les globals WebRTC ne sont pas viables → on garde la garde premier-plan.
        const canPrewarmRoom = AppState.currentState === 'active' || Platform.OS === 'ios';
        if (!canPrewarmRoom || warmRooms.has(callId)) return;
        let room: Room;
        try {
            const lk = await import('livekit-client'); // chargé UNIQUEMENT ici (différé) — jamais au boot
            room = new lk.Room({
                // Mêmes réglages que <LiveKitRoom> (CallScreen) : une Room passée ignore le prop `options`.
                videoCaptureDefaults: { resolution: lk.VideoPresets.h360.resolution },
                publishDefaults: { simulcast: false, videoCodec: 'h264', videoEncoding: lk.VideoPresets.h360.encoding },
                audioCaptureDefaults: { echoCancellation: true, noiseSuppression: true, autoGainControl: true },
            });
        } catch {
            return; // SDK non chargeable dans ce contexte → repli sur la Room de CallScreen
        }
        warmRooms.set(callId, room);
        try {
            await room.prepareConnection(t.url, t.token);
        } catch {
            // Échec de pré-chauffe → retirer + fermer (CallScreen repartira sur une Room fraîche).
            if (warmRooms.get(callId) === room) warmRooms.delete(callId);
            room.disconnect().catch(() => {});
        }
    })();
}

/** Récupère (et retire) la Room pré-chauffée d'un appel — consommée UNE seule fois par CallScreen (1ᵉʳ montage). */
export function consumePrewarmedRoom(callId: string): Room | undefined {
    const room = warmRooms.get(callId);
    if (room) warmRooms.delete(callId);
    return room;
}

/** Libère une Room pré-chauffée NON consommée (appel refusé / terminé avant décroché) → déconnexion propre. */
export function clearPrewarm(callId: string): void {
    const room = warmRooms.get(callId);
    if (room) {
        warmRooms.delete(callId);
        room.disconnect().catch(() => {});
    }
}
