import Taro from '@tarojs/taro';

export type AccentType = 'us' | 'uk';

const YOUDAO_TYPE: Record<AccentType, number> = {
  us: 1,
  uk: 2,
};

let currentAudio: HTMLAudioElement | null = null;
let currentInnerAudio: Taro.InnerAudioContext | null = null;

function pronunciationUrl(word: string, accent: AccentType) {
  return `https://dict.youdao.com/dictvoice?audio=${encodeURIComponent(word)}&type=${YOUDAO_TYPE[accent] || 1}`;
}

function stopCurrentAudio() {
  try {
    if (currentAudio) {
      currentAudio.pause();
      currentAudio.src = '';
      currentAudio = null;
    }
  } catch (_error) {
    // ignore playback cleanup errors
  }
  try {
    if (currentInnerAudio) {
      currentInnerAudio.stop();
      currentInnerAudio.destroy();
      currentInnerAudio = null;
    }
  } catch (_error) {
    // ignore playback cleanup errors
  }
  try {
    if (typeof window !== 'undefined' && 'speechSynthesis' in window) {
      window.speechSynthesis.cancel();
    }
  } catch (_error) {
    // ignore unsupported runtime
  }
}

function fallbackSpeech(word: string, accent: AccentType) {
  if (typeof window === 'undefined' || !('speechSynthesis' in window)) return false;
  try {
    const utterance = new SpeechSynthesisUtterance(word);
    utterance.lang = accent === 'uk' ? 'en-GB' : 'en-US';
    utterance.rate = 0.86;
    window.speechSynthesis.speak(utterance);
    return true;
  } catch (_error) {
    return false;
  }
}

export async function playWordPronunciation(word: string, accent: AccentType = 'us') {
  const text = word.trim();
  if (!text) return;
  stopCurrentAudio();

  const url = pronunciationUrl(text, accent);

  if (process.env.TARO_ENV === 'h5' && typeof Audio !== 'undefined') {
    try {
      const audio = new Audio(url);
      audio.preload = 'auto';
      currentAudio = audio;
      audio.onerror = () => {
        currentAudio = null;
        fallbackSpeech(text, accent);
      };
      await audio.play();
      return;
    } catch (_error) {
      if (fallbackSpeech(text, accent)) return;
    }
  }

  try {
    const audio = Taro.createInnerAudioContext();
    currentInnerAudio = audio;
    audio.src = url;
    audio.autoplay = true;
    audio.onEnded(() => {
      if (currentInnerAudio === audio) currentInnerAudio = null;
      audio.destroy();
    });
    audio.onError(() => {
      if (currentInnerAudio === audio) currentInnerAudio = null;
      audio.destroy();
    });
  } catch (_error) {
    Taro.showToast({ title: '当前环境暂不支持发音', icon: 'none' });
  }
}
