<template>
  <div ref="boxRef" style="flex: 1; position: relative">
    <div ref="containerRef" class="message-list" @scroll="handleScroll">
      <!-- 欢迎界面 -->
      <WelcomeScreen
        v-if="messages.length === 0"
        @select="$emit('select-suggestion', $event)"
      />

      <!-- 消息列表 -->
      <template v-else>
        <div class="messages-wrapper">
          <TransitionGroup name="message">
            <MessageBubble
              v-for="(message, index) in messages"
              :key="message.id"
              :message="message"
              :show-timestamp="showTimestamp"
              :compact="compact"
              :is-New="index === messages.length - 1"
              @retry="$emit('retry', message.id)"
              @regenerate="$emit('regenerate', message.id)"
              @copy="handleCopy(message)"
              @like="handleLike(message)"
              @dislike="handleDislike(message)"
              @select-suggestion="$emit('select-suggestion', $event.text)"
              @preview-image="handlePreviewImage"
              @play-video="handlePlayVideo"
              @download-file="handleDownloadFile"
            />
          </TransitionGroup>

          <!-- 正在输入指示器 -->
          <div v-if="isTyping" class="typing-indicator">
            <div class="typing-avatar">
              <Bot :size="20" />
            </div>
            <div class="typing-dots">
              <span></span>
              <span></span>
              <span></span>
            </div>
            <span class="typing-text">AI 正在思考...</span>
          </div>
        </div>
      </template>
    </div>
    <!-- 回到底部按钮 -->
    <Transition name="fade">
      <button
        v-if="showScrollButton"
        class="scroll-bottom-btn"
        @click="handleScrollToBottom"
      >
        <ChevronDown :size="20" />
        <span v-if="newMessageCount > 0" class="new-count">
          {{ newMessageCount }}
        </span>
      </button>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, nextTick, onMounted } from "vue";
import { useChatStore } from "@/stores/chat";
import MessageBubble from "@/components/message/MessageBubble.vue";
import WelcomeScreen from "./WelcomeScreen.vue";
import { Bot, ChevronDown } from "@/components/icons";
import type { Message, Attachment, VideoInfo } from "@/types/chat";

const props = withDefaults(
  defineProps<{
    messages: Message[];
    showTimestamp?: boolean;
    compact?: boolean;
    isTyping?: boolean;
  }>(),
  {
    showTimestamp: true,
    compact: false,
    isTyping: false,
  },
);

const emit = defineEmits<{
  retry: [messageId: string];
  regenerate: [messageId: string];
  "select-suggestion": [text: string];
  "preview-image": [image: Attachment, index: number];
  "play-video": [video: VideoInfo];
  "download-file": [file: Attachment];
}>();

const chatStore = useChatStore();

// 响应式状态
const boxRef: any = ref<HTMLElement | null>(null);
const containerRef: any = ref<HTMLElement | null>(null);
const showScrollButton = ref(false);
const newMessageCount = ref(0);
const isAutoScrolling = ref(true);
const lastScrollTop = ref(0);

onMounted(() => {
  containerRef.value.style.height = boxRef.value?.clientHeight + "px";
});

// 滚动处理
function handleScroll() {
  const container = containerRef.value;
  if (!container) return;

  const { scrollTop, scrollHeight, clientHeight } = container;
  const isAtBottom = scrollHeight - scrollTop - clientHeight < 100;

  if (scrollTop < lastScrollTop.value && !isAtBottom) {
    isAutoScrolling.value = false;
    showScrollButton.value = true;
  }

  if (isAtBottom) {
    isAutoScrolling.value = true;
    showScrollButton.value = false;
    newMessageCount.value = 0;
  }

  lastScrollTop.value = scrollTop;
}

// 滚动到底部
function scrollToBottom(smooth = true) {
  const container = containerRef.value;
  if (!container) return;

  container.scrollTo({
    top: container.scrollHeight,
    behavior: smooth ? "smooth" : "auto",
  });

  isAutoScrolling.value = true;
  showScrollButton.value = false;
  newMessageCount.value = 0;
}

// 按钮点击处理
function handleScrollToBottom() {
  scrollToBottom(true);
}

// 消息操作
function handleCopy(message: Message) {
  chatStore.setMessageCopied(message.id);
}

function handleLike(message: Message) {
  const currentLiked = message.feedback?.liked;
  chatStore.setMessageFeedback(message.id, currentLiked ? null : "like");
}

function handleDislike(message: Message) {
  const currentDisliked = message.feedback?.disliked;
  chatStore.setMessageFeedback(message.id, currentDisliked ? null : "dislike");
}

function handlePreviewImage(image: Attachment, index: number) {
  emit("preview-image", image, index);
}

function handlePlayVideo(video: VideoInfo) {
  emit("play-video", video);
}

function handleDownloadFile(file: Attachment) {
  emit("download-file", file);
}

// 监听消息变化
watch(
  () => props.messages.length,
  (newLen, oldLen) => {
    if (newLen > oldLen) {
      if (isAutoScrolling.value) {
        nextTick(() => {
          scrollToBottom(false);
        });
      } else {
        newMessageCount.value++;
      }
    }
  },
);

// 监听最后一条消息的内容变化
watch(
  () => props.messages[props.messages.length - 1]?.content.text,
  () => {
    if (isAutoScrolling.value) {
      nextTick(() => {
        const container = containerRef.value;
        if (container) {
          container.scrollTop = container.scrollHeight;
        }
      });
    }
  },
);

// 监听 isTyping 变化
watch(
  () => props.isTyping,
  (typing) => {
    if (typing && isAutoScrolling.value) {
      nextTick(() => {
        scrollToBottom(true);
      });
    }
  },
);

// 暴露方法
defineExpose({
  scrollToBottom,
});

onMounted(() => {
  scrollToBottom(false);
});
</script>

<style lang="scss" scoped>
.message-list {
  height: 500px;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
}

.messages-wrapper {
  display: flex;
  flex-direction: column;
  padding: 20px 0;
  min-height: 100%;
}

.typing-indicator {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 24px;
  animation: fadeIn 0.3s ease;
}

.typing-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%);
  border-radius: 12px;
  color: white;
}

.typing-dots {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 12px 16px;
  background: #f3f4f6;
  border-radius: 16px;

  .dark & {
    background: #2d2d3d;
  }

  span {
    width: 8px;
    height: 8px;
    background: #9ca3af;
    border-radius: 50%;
    animation: typingBounce 1.4s infinite ease-in-out both;

    &:nth-child(1) {
      animation-delay: -0.32s;
    }
    &:nth-child(2) {
      animation-delay: -0.16s;
    }
  }
}

.typing-text {
  font-size: 13px;
  color: #9ca3af;
}

.scroll-bottom-btn {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  background: white;
  color: #374151;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  cursor: pointer;
  transition: all 0.2s ease;
  z-index: 10;

  .dark & {
    background: #2d2d3d;
    color: #e5e7eb;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  }

  &:hover {
    transform: translateX(-50%) scale(1.1);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
  }

  .new-count {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    background: #ef4444;
    border-radius: 10px;
    color: white;
    font-size: 11px;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

// 消息过渡动画
.message-enter-active,
.message-leave-active {
  transition: all 0.3s ease;
}

.message-enter-from {
  opacity: 0;
  transform: translateY(20px);
}

.message-leave-to {
  opacity: 0;
  transform: translateX(-20px);
}

// 淡入淡出动画
.fade-enter-active,
.fade-leave-active {
  transition: all 0.2s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
  transform: translateX(-50%) translateY(10px);
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes typingBounce {
  0%,
  80%,
  100% {
    transform: scale(0.7);
    opacity: 0.5;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}
</style>
