/**
 * useSip.ts — React binding over SipEngine for the CORE calling app (no CallKeep).
 *
 * Manages the Android/iOS audio session with react-native-incall-manager:
 *   - start the audio session + ringback/ringtone at the right moments
 *   - route audio to speaker / earpiece on toggle
 * react-native-webrtc plays the remote audio track automatically once the
 * peer connection is up — no DOM <audio> element needed on native.
 */
import { useEffect, useRef, useState, useCallback } from 'react';
import InCallManager from 'react-native-incall-manager';
import { sipEngine, ActiveCall } from '../services/SipEngine';
import { CallPhase } from '../screens/ActiveCallScreen';

export interface UiCall {
  id: string;
  caller: string;
  direction: 'incoming' | 'outgoing';
  phase: CallPhase;
  muted: boolean;
  speaker: boolean;
  held: boolean;
}

function uuid(): string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

export function useSip() {
  const [registered, setRegistered] = useState(sipEngine.isRegistered);
  const [call, setCall] = useState<UiCall | null>(null);

  const patch = useCallback((p: Partial<UiCall>) => {
    setCall((c) => (c ? { ...c, ...p } : c));
  }, []);

  useEffect(() => {
    const onReg = () => setRegistered(true);
    const onUnreg = () => setRegistered(false);
    const onRegFail = () => setRegistered(false);

    const onIncoming = (c: ActiveCall) => {
      // Ring + set up the audio session for a possible answer.
      InCallManager.startRingtone('_DEFAULT_');
      setCall({
        id: c.id, caller: c.remoteNumber, direction: 'incoming',
        phase: 'ringing', muted: false, speaker: false, held: false,
      });
    };
    const onProgress = () => {
      InCallManager.start({ media: 'audio' });
      InCallManager.startRingback('_DTMF_'); // caller hears ringback
      patch({ phase: 'ringing' });
    };
    const onAccepted = () => patch({ phase: 'connecting' });
    const onConfirmed = () => {
      InCallManager.stopRingback();
      InCallManager.stopRingtone();
      InCallManager.start({ media: 'audio' }); // ensure audio session is active
      patch({ phase: 'active' });
    };
    const onEnded = (id: string) => {
      InCallManager.stopRingback();
      InCallManager.stopRingtone();
      InCallManager.stop();
      patch({ phase: 'ended' });
      setTimeout(() => setCall((c) => (c && c.id === id ? null : c)), 900);
    };

    sipEngine.on('registered', onReg);
    sipEngine.on('unregistered', onUnreg);
    sipEngine.on('registrationFailed', onRegFail);
    sipEngine.on('incoming', onIncoming);
    sipEngine.on('progress', onProgress);
    sipEngine.on('accepted', onAccepted);
    sipEngine.on('confirmed', onConfirmed);
    sipEngine.on('ended', onEnded);

    return () => {
      sipEngine.off('registered', onReg);
      sipEngine.off('unregistered', onUnreg);
      sipEngine.off('registrationFailed', onRegFail);
      sipEngine.off('incoming', onIncoming);
      sipEngine.off('progress', onProgress);
      sipEngine.off('accepted', onAccepted);
      sipEngine.off('confirmed', onConfirmed);
      sipEngine.off('ended', onEnded);
    };
  }, [patch]);

  const placeCall = useCallback((number: string) => {
    const id = uuid();
    InCallManager.start({ media: 'audio' });
    sipEngine.placeCall(number, id);
    setCall({
      id, caller: number, direction: 'outgoing',
      phase: 'connecting', muted: false, speaker: false, held: false,
    });
  }, []);

  const answer = useCallback(() => {
    if (!call) return;
    InCallManager.stopRingtone();
    InCallManager.start({ media: 'audio' });
    sipEngine.answer(call.id);
    patch({ phase: 'connecting' });
  }, [call, patch]);

  const hangup = useCallback(() => {
    if (call) sipEngine.hangup(call.id);
  }, [call]);

  const toggleMute = useCallback(() => {
    if (!call) return;
    const next = !call.muted;
    sipEngine.setMute(call.id, next);
    patch({ muted: next });
  }, [call, patch]);

  const toggleHold = useCallback(() => {
    if (!call) return;
    const next = !call.held;
    sipEngine.setHold(call.id, next);
    patch({ held: next, phase: next ? 'held' : 'active' });
  }, [call, patch]);

  const toggleSpeaker = useCallback(() => {
    if (!call) return;
    const next = !call.speaker;
    InCallManager.setForceSpeakerphoneOn(next);
    patch({ speaker: next });
  }, [call, patch]);

  return {
    registered, call,
    placeCall, answer, hangup, toggleMute, toggleHold, toggleSpeaker,
  };
}
