<script setup lang="ts">
import { onBeforeUnmount, ref } from 'vue';

import { copyTextToClipboard } from '@easyflow/utils';

import { Check, CopyDocument, RefreshRight } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';

import ChatAnswerVariantNavigator from './ChatAnswerVariantNavigator.vue';

const props = withDefaults(
  defineProps<{
    align?: 'end' | 'start';
    allowCopy?: boolean;
    allowRegenerate?: boolean;
    copyErrorMessage?: string;
    copyText?: string;
    disabledVariantNext?: boolean;
    disabledVariantPrevious?: boolean;
    regenerateDisabled?: boolean;
    showVariantNavigator?: boolean;
    variantLoading?: boolean;
    variantCurrent?: number;
    variantTotal?: number;
  }>(),
  {
    align: 'start',
    allowCopy: false,
    allowRegenerate: false,
    copyErrorMessage: '复制失败',
    copyText: '',
    disabledVariantNext: false,
    disabledVariantPrevious: false,
    regenerateDisabled: false,
    showVariantNavigator: false,
    variantLoading: false,
    variantCurrent: 1,
    variantTotal: 1,
  },
);

const emit = defineEmits<{
  regenerate: [];
  selectNextVariant: [];
  selectPreviousVariant: [];
}>();

const copied = ref(false);
const copying = ref(false);
const COPIED_FEEDBACK_DURATION_MS = 1600;
let copiedResetTimer: ReturnType<typeof setTimeout> | undefined;

async function handleCopy() {
  if (copying.value || !props.copyText) {
    return;
  }
  copying.value = true;
  try {
    await copyTextToClipboard(props.copyText);
    copied.value = true;
    if (copiedResetTimer) {
      clearTimeout(copiedResetTimer);
    }
    copiedResetTimer = setTimeout(() => {
      copied.value = false;
      copiedResetTimer = undefined;
    }, COPIED_FEEDBACK_DURATION_MS);
  } catch (error) {
    console.error('复制消息失败:', error);
    ElMessage.error(props.copyErrorMessage);
  } finally {
    copying.value = false;
  }
}

function handleRegenerate() {
  if (props.regenerateDisabled) {
    return;
  }
  emit('regenerate');
}

function handleSelectPreviousVariant() {
  emit('selectPreviousVariant');
}

function handleSelectNextVariant() {
  emit('selectNextVariant');
}

onBeforeUnmount(() => {
  if (copiedResetTimer) {
    clearTimeout(copiedResetTimer);
  }
});
</script>

<template>
  <div
    v-if="allowCopy || allowRegenerate || showVariantNavigator"
    class="message-actions"
    :class="`is-${align}`"
  >
    <ChatAnswerVariantNavigator
      v-if="showVariantNavigator"
      :current="variantCurrent"
      :total="variantTotal"
      :disabled-prev="disabledVariantPrevious"
      :disabled-next="disabledVariantNext"
      :loading="variantLoading"
      @previous="handleSelectPreviousVariant"
      @next="handleSelectNextVariant"
    />

    <button
      v-if="allowCopy"
      type="button"
      class="message-actions__button"
      :aria-busy="copying"
      :aria-label="copied ? '复制成功' : '复制消息'"
      :title="copied ? '复制成功' : '复制'"
      @click="handleCopy"
    >
      <Transition name="message-actions__icon" mode="out-in">
        <Check v-if="copied" key="check" />
        <CopyDocument v-else key="copy" />
      </Transition>
    </button>

    <button
      v-if="allowRegenerate"
      type="button"
      class="message-actions__button"
      :disabled="regenerateDisabled"
      aria-label="重新生成"
      title="重新生成"
      @click="handleRegenerate"
    >
      <RefreshRight />
    </button>
  </div>
</template>

<style scoped>
.message-actions {
  display: inline-flex;
  gap: 4px;
  align-items: center;
  margin-top: 6px;
}

.message-actions.is-end {
  justify-content: flex-end;
}

.message-actions__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  color: hsl(var(--text-muted));
  cursor: pointer;
  border: none;
  border-radius: 999px;
  background: transparent;
  transition:
    color 0.18s ease,
    background-color 0.18s ease;
}

.message-actions__button:hover:not(:disabled) {
  color: hsl(var(--text-strong));
  background: hsl(var(--foreground) / 0.05);
}

.message-actions__button:focus-visible {
  outline: 2px solid hsl(var(--primary) / 0.32);
  outline-offset: 2px;
}

.message-actions__button:disabled {
  opacity: 0.42;
  cursor: not-allowed;
}

.message-actions__button :deep(svg) {
  width: 15px;
  height: 15px;
}

.message-actions__icon-enter-active,
.message-actions__icon-leave-active {
  transition:
    opacity var(--motion-duration-fast) var(--motion-ease-standard),
    transform var(--motion-duration-fast) var(--motion-ease-standard);
}

.message-actions__icon-enter-from,
.message-actions__icon-leave-to {
  opacity: 0;
  transform: scale(0.88);
}
</style>
