<script setup lang="ts">
import { computed, h, readonly, ref, shallowRef, watch } from 'vue'
import { SelectOption, SelectRenderTag } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { Howl } from 'howler'
import { useSystemLanguageStore } from '@/store/modules/system-language'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
import { fetchGetTimbreList } from '@/apis/timber'
import { TimbreLanguageInfoItem, TimbreInfoItem } from '../../types'
import { validBrowser } from '@/utils/browser-detection'

interface Props {
  modalTitle: string
  isShowModal: boolean
  btnLoading: boolean
  timbreInfo?: TimbreLanguageInfoItem
}

interface Emits {
  (e: 'update:isShowModal', value: boolean): void
  (e: 'confirm', value: string): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const { t } = useI18n()

const systemLanguageStore = useSystemLanguageStore()

const languageInfoList = ref<TimbreLanguageInfoItem[]>([])
const timbreInfoList = ref<TimbreInfoItem[]>([])
const timbreOptionList = ref<SelectOption[]>([])
const selectedLanguage = ref('')
const selectedTimberId = ref('')
const timberUrl = ref('')
const isPlaySound = ref(false)
const requestDataLoading = ref(false)
const currentSoundCtl = shallowRef<Howl | null>(null)

let timbreRenderTag: SelectRenderTag

const languageOptions = readonly([
  { label: () => h('span', {}, t('common_module.mandarin')), value: 'zh-CN' },
  { label: () => h('span', {}, t('common_module.cantonese')), value: 'zh-HK' },
  { label: () => h('span', {}, t('common_module.english')), value: 'en' },
])

const showModal = computed({
  get() {
    return props.isShowModal
  },
  set(value: boolean) {
    handleAudioPause()
    emit('update:isShowModal', value)
  },
})

const isHasTimberUrl = computed(() => {
  return !!timberUrl.value
})

const confirmBtnDisabled = computed(() => {
  return requestDataLoading.value || !selectedTimberId.value
})

watch(
  () => showModal.value,
  (value) => {
    value && handleGetTimberList()
  },
)

async function handleGetTimberList() {
  requestDataLoading.value = true
  selectedLanguage.value = props.timbreInfo?.matchLang || systemLanguageStore.currentLanguageInfo.key

  const res = await fetchGetTimbreList<TimbreLanguageInfoItem[]>()

  if (res.code === 0) {
    requestDataLoading.value = false
    languageInfoList.value = res.data
    timbreInfoList.value =
      languageInfoList.value.find((item) => item.matchLang === selectedLanguage.value)?.timbreInfo || []
    selectedTimberId.value = props.timbreInfo?.timbreInfo?.[0]?.timbreId || timbreInfoList.value?.[0]?.timbreId || ''
    timberUrl.value = props.timbreInfo?.timbreInfo?.[0]?.voiceUrl || timbreInfoList.value?.[0]?.voiceUrl || ''

    handleRenderTimbreOption()
  }
}

function handleRenderTimbreOption() {
  timbreOptionList.value = timbreInfoList.value.map((item) => {
    return {
      label: () =>
        h('div', { class: 'flex items-baseline justify-between w-[180px]' }, [
          h('span', { class: 'max-w-[160px] line-clamp-1 whitespace-normal' }, { default: () => item.timbreName }),

          h('i', {
            class: {
              'iconfont icon-playing ': item.isPlaying,
              'iconfont icon-stop text-[14px]': !item.isPlaying,
              'text-theme-color text-[14px]': true,
            },
            onClick: (e) => {
              e.stopPropagation()

              timbreInfoList.value.forEach((mockItem) => {
                if (mockItem.timbreId !== item.timbreId) {
                  mockItem.isPlaying = false
                }
              })

              isPlaySound.value = false

              item.isPlaying = !item.isPlaying

              if (item.isPlaying) {
                handleAudioPlay(item.voiceUrl)
              }
            },
          }),
        ]),
      value: item.timbreId,
      nickName: item.timbreName,
      timberUrl: item.voiceUrl,
    }
  })

  timbreRenderTag = ({ option }) => {
    return h('span', {}, { default: () => option.nickName as string })
  }
}

function handleUpdateTimberLanguage(value: string) {
  timbreInfoList.value = languageInfoList.value.find((item) => item.matchLang === value)?.timbreInfo || []
  selectedTimberId.value = timbreInfoList.value?.[0].timbreId || ''
  timberUrl.value = timbreInfoList.value?.[0].voiceUrl || ''
  isPlaySound.value = false
  handleAudioPause()
  handleRenderTimbreOption()
}

function handleUpdateTimber(_value: string, option: SelectOption) {
  timberUrl.value = option.timberUrl as string
}

function handleClickTimber() {
  isPlaySound.value = !isPlaySound.value

  if (isPlaySound.value) {
    timbreInfoList.value.forEach((item) => (item.isPlaying = false))
    handleAudioPlay(timberUrl.value)
  } else {
    handleAudioPause()
  }
}

function handleUpdateTimberId() {
  selectedTimberId.value && emit('confirm', selectedTimberId.value)
}

function howlSoundFactory(url: string) {
  const soundCtl = new Howl({
    src: [url],
    format: ['mpeg'],
    html5: !validBrowser(),
    preload: true,
    autoplay: true,
    onplay: () => {
      currentSoundCtl.value = soundCtl
    },
    onend: () => {
      soundCtl.unload()

      timbreInfoList.value.forEach((timbreItem) => (timbreItem.isPlaying = false))
      isPlaySound.value = false
    },
  })

  return soundCtl
}

function handleAudioPlay(audioUrl: string) {
  if (currentSoundCtl.value) {
    currentSoundCtl.value.pause()
    currentSoundCtl.value.unload()
    currentSoundCtl.value = null
  }

  howlSoundFactory(audioUrl)
}

function handleAudioPause() {
  if (currentSoundCtl.value) {
    currentSoundCtl.value.pause()
    currentSoundCtl.value.unload()
    currentSoundCtl.value = null
  }

  timbreInfoList.value.forEach((timbreItem) => (timbreItem.isPlaying = false))
  isPlaySound.value = false
}
</script>

<template>
  <CustomModal
    v-model:is-show="showModal"
    :title="modalTitle"
    :btn-loading="btnLoading"
    :btn-disabled="confirmBtnDisabled"
    :width="515"
    :height="378"
    @confirm="handleUpdateTimberId"
  >
    <template #content>
      <div class="text-gray-font-color mb-2">
        {{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.setting_voice_message') }}
      </div>

      <div v-show="!requestDataLoading" class="flex items-center gap-3">
        <n-select
          v-model:value="selectedLanguage"
          class="w-[211px]!"
          :options="languageOptions"
          @update:value="handleUpdateTimberLanguage"
        />
        <n-select
          v-model:value="selectedTimberId"
          class="w-[211px]!"
          :options="timbreOptionList"
          :render-tag="timbreRenderTag"
          :show-checkmark="false"
          @update:value="handleUpdateTimber"
        />
        <div
          class="flex h-5 w-5 items-center justify-center rounded-full bg-[#eff0ff]"
          :class="isHasTimberUrl ? 'cursor-pointer' : 'cursor-not-allowed opacity-50'"
        >
          <i
            class="iconfont text-theme-color text-[13px] leading-[13px]"
            :class="isPlaySound ? 'icon-playing' : 'icon-stop'"
            @click="handleClickTimber"
          />
        </div>
      </div>

      <div v-show="requestDataLoading" class="flex items-center gap-3">
        <n-skeleton height="32px" />
        <n-skeleton height="32px" />
        <n-skeleton height="20px" width="20px" circle class="flex-shrink-0" />
      </div>
    </template>
  </CustomModal>
</template>
