'use client';

import { useCallback, useEffect, useRef, useState } from 'react';
import type { Call, Device } from '@twilio/voice-sdk';
import { api } from '@/lib/api-client';

export type CallState = 'idle' | 'connecting' | 'ringing' | 'in_call' | 'ended' | 'error';

/**
 * Twilio 网页点击拨号 hook(@twilio/voice-sdk)。
 *
 * 流程:dial(planId) → 拿 AccessToken → 建 Device → device.connect({ params:{ planId } })
 *       → Twilio 回调后端 /twilio/voice 返回 <Dial> → 桥接患者手机。
 *
 * Device/SDK 动态 import(只在点击时加载,避免 SSR + 首屏体积)。
 */
export function useTwilioCall() {
  const [state, setState] = useState<CallState>('idle');
  const [error, setError] = useState<string | null>(null);
  const [muted, setMuted] = useState(false);
  const [seconds, setSeconds] = useState(0);

  const deviceRef = useRef<Device | null>(null);
  const callRef = useRef<Call | null>(null);
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const stopTimer = () => {
    if (timerRef.current) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
  };

  const cleanup = useCallback(() => {
    stopTimer();
    callRef.current = null;
    if (deviceRef.current) {
      try {
        deviceRef.current.destroy();
      } catch {
        /* noop */
      }
      deviceRef.current = null;
    }
  }, []);

  useEffect(() => cleanup, [cleanup]);

  const hangup = useCallback(() => {
    try {
      callRef.current?.disconnect();
      deviceRef.current?.disconnectAll();
    } catch {
      /* noop */
    }
    stopTimer();
    setState('ended');
  }, []);

  const toggleMute = useCallback(() => {
    const c = callRef.current;
    if (!c) return;
    const next = !muted;
    c.mute(next);
    setMuted(next);
  }, [muted]);

  const dial = useCallback(async (planId: string) => {
    setError(null);
    setMuted(false);
    setSeconds(0);
    setState('connecting');
    try {
      const { token } = await api.post<{ token: string; identity: string }>(
        '/pac/v1/twilio/token',
      );
      const { Device } = await import('@twilio/voice-sdk');
      const device = new Device(token, {
        codecPreferences: ['opus', 'pcmu'] as never,
        logLevel: 'error' as never,
      });
      deviceRef.current = device;

      const call = await device.connect({ params: { planId } });
      callRef.current = call;

      call.on('ringing', () => setState('ringing'));
      call.on('accept', () => {
        setState('in_call');
        stopTimer();
        timerRef.current = setInterval(() => setSeconds((s) => s + 1), 1000);
      });
      call.on('disconnect', () => {
        stopTimer();
        setState('ended');
      });
      call.on('cancel', () => {
        stopTimer();
        setState('ended');
      });
      call.on('error', (e: { message?: string }) => {
        stopTimer();
        setError(e?.message ?? '通话错误');
        setState('error');
      });
    } catch (e) {
      setError(e instanceof Error ? e.message : '拨号失败');
      setState('error');
      cleanup();
    }
  }, [cleanup]);

  const reset = useCallback(() => {
    cleanup();
    setState('idle');
    setError(null);
    setSeconds(0);
    setMuted(false);
  }, [cleanup]);

  return { state, error, muted, seconds, dial, hangup, toggleMute, reset };
}
