<script setup>
import { useNamespace, useLocale } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import { computed, ref, onBeforeUnmount, watch } from "vue";
import { aiVoiceTriggerProps, aiVoiceTriggerEmits } from "./ai-voice-trigger";
import { YhIcon } from "../../icon";
defineOptions({
  name: "YhAiVoiceTrigger"
});
const props = defineProps(aiVoiceTriggerProps);
const emit = defineEmits(aiVoiceTriggerEmits);
const ns = useNamespace("ai-voice-trigger");
const { t } = useLocale();
const { themeStyle } = useComponentTheme(
  "ai-voice-trigger",
  computed(() => props.themeOverrides)
);
const localRecording = ref(props.recording);
let visualizerTimer = null;
const simulatedAmplitudes = ref(Array(20).fill(5));
watch(
  () => props.amplitudes,
  (newAmps) => {
    if (newAmps && newAmps.length > 0) {
      const hasData = newAmps.some((a) => a > 6 || a > 0 && a !== 5);
      if (hasData) {
        simulatedAmplitudes.value = [...newAmps];
      }
    }
  },
  { immediate: true, deep: true }
);
const syncAmplitudes = () => {
  if (props.recording || localRecording.value) {
    const hasData = props.amplitudes && props.amplitudes.some((a) => a > 6 || a > 0 && a !== 5);
    if (!hasData) {
      simulatedAmplitudes.value = Array.from({ length: 20 }, () => 10 + Math.random() * 40);
    }
  }
};
const toggleRecording = () => {
  if (props.recording === void 0 || props.recording === null) {
    localRecording.value = !localRecording.value;
    if (localRecording.value) {
      emit("update:recording", true);
      emit("start");
      startVisualizer();
    } else {
      emit("update:recording", false);
      emit("stop");
      stopVisualizer();
    }
    return;
  }
  const newStatus = !props.recording;
  emit("update:recording", newStatus);
  if (newStatus) {
    emit("start");
    startVisualizer();
  } else {
    emit("stop");
    stopVisualizer();
  }
};
const handleCancel = (e) => {
  e.stopPropagation();
  if (props.recording === void 0 || props.recording === null) {
    localRecording.value = false;
  }
  emit("update:recording", false);
  emit("stop");
  emit("cancel");
  stopVisualizer();
};
const startVisualizer = () => {
  if (visualizerTimer) clearInterval(visualizerTimer);
  visualizerTimer = setInterval(syncAmplitudes, 150);
};
const stopVisualizer = () => {
  if (visualizerTimer) {
    clearInterval(visualizerTimer);
    visualizerTimer = null;
  }
  simulatedAmplitudes.value = Array(20).fill(5);
};
onBeforeUnmount(() => {
  if (visualizerTimer) clearInterval(visualizerTimer);
});
const isCurrentlyRecording = computed(
  () => props.recording !== void 0 ? props.recording : localRecording.value
);
watch(isCurrentlyRecording, (active) => {
  if (active) startVisualizer();
  else stopVisualizer();
});
</script>

<template>
  <Teleport to="body" :disabled="props.variant === 'inline' || !props.teleport">
    <div
      :class="[ns.b(), ns.m(props.variant), ns.m(props.position), ns.is('recording', isCurrentlyRecording)]"
      :style="[props.variant !== 'inline' ? {
  position: props.teleport ? 'fixed' : 'relative',
  [props.position.split('-')[0]]: props.teleport ? props.offset[0] + 'px' : 'auto',
  [props.position.split('-')[1]]: props.teleport ? props.offset[1] + 'px' : 'auto'
} : {}, themeStyle]"
    >
      <div :class="ns.e('body')">
        <!-- Waveform Visualizer -->
        <Transition name="yh-voice-expand">
          <div v-if="isCurrentlyRecording" :class="ns.e('visualizer')">
            <!-- Sphere Visualizer (Pulsing Ball) -->
            <template v-if="props.variant === 'sphere'">
              <div :class="ns.e('sphere-glow')"></div>
              <div
                v-for="i in 3"
                :key="i"
                :class="ns.e('sphere-pulse')"
                :style="{
  animationDelay: i * 0.5 + 's',
  transform: `scale(${1 + (simulatedAmplitudes[i] || 0) / 100})`
}"
              ></div>
            </template>

            <!-- Standard Wave Visualizer -->
            <div v-else :class="ns.e('bars')">
              <span
                v-for="(amp, i) in simulatedAmplitudes"
                :key="i"
                :style="{
  height: amp + 'px'
}"
                :class="ns.e('bar')"
              ></span>
            </div>

            <span v-if="props.variant !== 'sphere'" :class="ns.e('hint')">{{
              t("ai.voice.listening")
            }}</span>

            <!-- Cancel Button -->
            <button :class="ns.e('cancel')" @click="handleCancel" title="Cancel">
              <YhIcon name="close" />
            </button>
          </div>
        </Transition>

        <!-- Main Trigger Button -->
        <button
          :class="[ns.e('trigger'), {
  'is-active': isCurrentlyRecording
}]"
          @click="toggleRecording"
        >
          <span :class="ns.e('mic')">
            <template v-if="props.variant === 'sphere' && isCurrentlyRecording">
              <div :class="ns.e('sphere-inner')"></div>
            </template>
            <YhIcon v-else :name="isCurrentlyRecording ? 'video-pause' : 'microphone'" />
          </span>
          <span v-if="!isCurrentlyRecording && props.variant === 'inline'" :class="ns.e('label')">
            <slot>{{ t("ai.voice.trigger") }}</slot>
          </span>
        </button>
      </div>
    </div>
  </Teleport>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
@keyframes yh-pulse-mic {
  0% {
    box-shadow: 0 0 0 0 var(--yh-ai-voice-trigger-active-color, #f56c6c);
    opacity: 0.4;
  }
  70% {
    box-shadow: 0 0 0 8px transparent;
    opacity: 0;
  }
  100% {
    box-shadow: 0 0 0 0 transparent;
  }
}
@keyframes yh-fade-breath {
  0%, 100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}
@keyframes yh-sphere-pulse {
  0% {
    transform: scale(1);
    opacity: 0.5;
  }
  100% {
    transform: scale(3);
    opacity: 0;
  }
}
@keyframes yh-sphere-glow {
  0% {
    transform: scale(1);
    opacity: 0.4;
  }
  100% {
    transform: scale(1.5);
    opacity: 0.8;
  }
}
@keyframes yh-sphere-float {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}
@keyframes yh-sphere-inner-pulse {
  0% {
    opacity: 0.7;
    transform: scale(0.8);
  }
  100% {
    opacity: 1;
    transform: scale(1.1);
  }
}
.yh-voice-expand-enter-active,
.yh-voice-expand-leave-active {
  transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}

.yh-voice-expand-enter-from,
.yh-voice-expand-leave-to {
  width: 0 !important;
  padding: 0 !important;
  opacity: 0;
  transform: translateX(10px);
}

.yh-ai-voice-trigger {
  --yh-ai-voice-trigger-btn-size: 32px;
  --yh-ai-voice-trigger-bg: var(--yh-bg-color-overlay, var(--yh-bg-color, #ffffff));
  --yh-ai-voice-trigger-active-color: var(--yh-color-danger, #f56c6c);
  --yh-ai-voice-trigger-wave-color: var(--yh-color-danger, #f56c6c);
  display: inline-flex;
  align-items: center;
  position: relative;
  font-family: var(--yh-font-family);
}
.yh-ai-voice-trigger--floating {
  z-index: 2000;
}
.yh-ai-voice-trigger--floating .yh-ai-voice-trigger__body {
  box-shadow: var(--yh-box-shadow-dark);
  border: 1px solid var(--yh-border-color-lighter);
}

.yh-ai-voice-trigger--sphere {
  --yh-ai-voice-trigger-btn-size: 56px;
  z-index: 2000;
}
.yh-ai-voice-trigger--sphere .yh-ai-voice-trigger__body {
  padding: 0;
  background: transparent !important;
  box-shadow: none !important;
  overflow: visible;
}

.yh-ai-voice-trigger--sphere .yh-ai-voice-trigger__trigger {
  background: var(--yh-color-primary) !important;
  color: #fff !important;
  box-shadow: 0 4px 12px rgba(var(--yh-color-primary-rgb), 0.4);
  z-index: 2;
}
.yh-ai-voice-trigger--sphere .yh-ai-voice-trigger__trigger.is-active {
  animation: yh-sphere-float 3s ease-in-out infinite;
}

.yh-ai-voice-trigger--sphere .yh-ai-voice-trigger__sphere-glow {
  position: absolute;
  width: 100%;
  height: 100%;
  background: radial-gradient(circle, var(--yh-color-primary-light-3) 0%, transparent 70%);
  filter: blur(10px);
  opacity: 0.6;
  animation: yh-sphere-glow 2s infinite alternate;
}

.yh-ai-voice-trigger--sphere .yh-ai-voice-trigger__sphere-pulse {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 2px solid var(--yh-color-primary-light-5);
  opacity: 0;
  animation: yh-sphere-pulse 2s infinite;
}

.yh-ai-voice-trigger--sphere .yh-ai-voice-trigger__sphere-inner {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--yh-bg-color, #fff);
  animation: yh-sphere-inner-pulse 1s infinite alternate;
}

.yh-ai-voice-trigger__body {
  display: flex;
  align-items: center;
  background-color: var(--yh-ai-voice-trigger-bg);
  border-radius: 20px;
  padding: 4px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  position: relative;
  overflow: hidden;
}
.yh-ai-voice-trigger__body:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.yh-ai-voice-trigger__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  cursor: pointer;
  border-radius: 50%;
  min-width: var(--yh-ai-voice-trigger-btn-size);
  height: var(--yh-ai-voice-trigger-btn-size);
  color: var(--yh-text-color-primary, #303133);
  transition: all 0.2s;
  flex-shrink: 0;
  position: relative;
  padding: 0;
}
.yh-ai-voice-trigger__trigger .yh-icon {
  font-size: 16px;
  transition: transform 0.2s;
}
.yh-ai-voice-trigger__trigger:hover {
  background-color: var(--yh-fill-color-light, #f5f7fa);
  color: var(--yh-color-primary, #409eff);
}
.yh-ai-voice-trigger__trigger.is-active {
  background-color: var(--yh-ai-voice-trigger-active-color);
  color: #fff !important;
  animation: yh-pulse-mic 2s infinite;
}
.yh-ai-voice-trigger__trigger.is-active .yh-icon {
  transform: scale(0.9);
}

.yh-ai-voice-trigger--inline .yh-ai-voice-trigger__trigger:not(.is-active) {
  width: auto;
  padding: 0 12px;
  border-radius: 16px;
  border: 1px solid var(--yh-border-color-lighter);
  background-color: var(--yh-bg-color);
}
.yh-ai-voice-trigger--inline .yh-ai-voice-trigger__trigger:not(.is-active):hover {
  border-color: var(--yh-color-primary);
  background-color: var(--yh-color-primary-light-9);
}

.yh-ai-voice-trigger__visualizer {
  display: flex;
  align-items: center;
  padding: 0 12px 0 8px;
  gap: 12px;
  overflow: hidden;
}

.yh-ai-voice-trigger__bars {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 24px;
  width: 140px;
}

.yh-ai-voice-trigger__bar {
  width: 3px;
  background-color: var(--yh-ai-voice-trigger-wave-color);
  border-radius: 2px;
  transition: height 0.15s ease-out;
  min-height: 4px;
  opacity: 0.8;
}

.yh-ai-voice-trigger__hint {
  font-size: 12px;
  color: var(--yh-text-color-secondary, #909399);
  white-space: nowrap;
  animation: yh-fade-breath 2s infinite;
}

.yh-ai-voice-trigger__cancel {
  background: transparent;
  border: none;
  color: var(--yh-text-color-secondary, #909399);
  cursor: pointer;
  padding: 4px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.6;
  transition: all 0.2s;
}
.yh-ai-voice-trigger__cancel:hover {
  background: var(--yh-fill-color, #f0f2f5);
  opacity: 1;
  color: var(--yh-color-danger, #f56c6c);
}
</style>
