<template>
  <div class="message-list-container">
    <!-- 消息选择操作栏 -->
    <Transition name="slide-down">
      <div v-if="isMessageSelectMode" class="message-select-bar">
        <div class="select-info">
          <span class="select-count">已选择 {{ selectedMessageCount }} 条消息</span>
        </div>
        <div class="select-actions">
          <button class="action-btn select-all" @click="handleSelectAll">
            全选
          </button>
          <button class="action-btn cancel" @click="handleCancelSelect">
            取消
          </button>
          <button class="action-btn confirm" :disabled="selectedMessageCount === 0" @click="handleConfirmShare">
            确认分享
          </button>
        </div>
      </div>
    </Transition>

    <div ref="containerRef" class="message-list" @scroll="handleScroll">
      <!-- 欢迎界面 -->
      <WelcomeScreen v-if="visibleMessages.length === 0" @select="$emit('select-suggestion', $event)" />

      <!-- 消息列表 -->
      <template v-else>
        <div class="messages-wrapper">
          <TransitionGroup name="message">
            <MessageBubble v-for="(message, index) in visibleMessages" :key="message.id" :message="message"
              :show-timestamp="showTimestamp" :compact="compact" :is-New="index === visibleMessages.length - 1"
              :is-message-select-mode="isMessageSelectMode" :is-selected="isMessageSelected(message.id)"
              @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)" @preview-image="handlePreviewImage"
              @play-video="handlePlayVideo" @download-file="handleDownloadFile"
              @toggle-select="handleToggleMessageSelect(message.id)"
              @enter-select-mode="handleEnterSelectMode(message.id)" />
          </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, computed } from "vue";
import { useChatStore } from "@/stores/chat";
import { useSettingsStore } from "@/stores/settings";
import MessageBubble from "@/components/message/MessageBubble.vue";
import WelcomeScreen from "./WelcomeScreen.vue";
import { Bot, ChevronDown } from "@/components/icons";
import type { Message, Attachment, VideoInfo, Suggestion } from "@/types/chat";
import { MessageRole } from "@/types/chat";

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

// 过滤掉系统消息，不显示在前端
const visibleMessages = computed(() => {
  return props.messages.filter(
    (message) => message.role !== MessageRole.SYSTEM
  );
});

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

const chatStore = useChatStore();
const settingsStore = useSettingsStore();

// 消息选择模式状态
const isMessageSelectMode = computed(() => chatStore.isMessageSelectMode);
const selectedMessageCount = computed(() => chatStore.selectedMessageCount);

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

// 高度通过 CSS flex 布局自适应，不需要手动设置

// 滚动处理
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);
}

// 消息选择模式方法
function handleEnterSelectMode(messageId: string) {
  chatStore.enterMessageSelectMode(chatStore.currentConversationId || '', messageId);
}

function handleToggleMessageSelect(messageId: string) {
  chatStore.toggleMessageSelection(messageId);
}

function handleSelectAll() {
  chatStore.selectAllMessages();
}

function handleCancelSelect() {
  chatStore.exitMessageSelectMode();
}

function handleConfirmShare() {
  if (chatStore.selectedMessageCount > 0) {
    settingsStore.openShareModal();
  }
}

function isMessageSelected(messageId: string): boolean {
  return chatStore.isMessageSelected(messageId);
}

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

// 监听最后一条消息的内容变化
watch(
  () => visibleMessages.value[visibleMessages.value.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(() => {
  // 只有当有消息时才滚动到底部，否则保持在顶部显示欢迎界面
  if (visibleMessages.value.length > 0) {
    scrollToBottom(false);
  }
});
</script>

<style lang="scss" scoped>
.message-list-container {
  flex: 1;
  position: relative;
  min-height: 0;
}

.message-list {
  height: 100%;
  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: 14px;
  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;
  }
}

// 消息选择操作栏
.message-select-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  background: white;
  border-bottom: 1px solid #e5e7eb;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);

  .dark & {
    background: #1e1e2e;
    border-bottom-color: #2d2d3d;
  }
}

.select-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.select-count {
  font-size: 14px;
  font-weight: 500;
  color: #374151;

  .dark & {
    color: #e5e7eb;
  }
}

.select-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.action-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;

  &.select-all,
  &.cancel {
    background: #f3f4f6;
    color: #6b7280;

    .dark & {
      background: #2d2d3d;
      color: #9ca3af;
    }

    &:hover {
      background: #e5e7eb;

      .dark & {
        background: #374151;
      }
    }
  }

  &.confirm {
    background: #3b82f6;
    color: white;

    &:hover:not(:disabled) {
      background: #2563eb;
    }

    &:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
  }
}

// 滑入动画
.slide-down-enter-active,
.slide-down-leave-active {
  transition: all 0.3s ease;
}

.slide-down-enter-from,
.slide-down-leave-to {
  opacity: 0;
  transform: translateY(-100%);
}
</style>
