<script setup>
import { useNamespace, useLocale } from "@yh-ui/hooks";
import { watch, nextTick, computed } from "vue";
import YhAiSender from "../../ai-sender/src/ai-sender.vue";
import YhAiBubble from "../../ai-bubble/src/ai-bubble.vue";
import { YhButton } from "../../button";
import { YhIcon } from "../../icon";
import { aiChatProps, aiChatEmits } from "./ai-chat";
import { useComponentTheme } from "@yh-ui/theme";
import { useVirtualScroll } from "@yh-ui/hooks";
defineOptions({
  name: "YhAiChat"
});
const props = defineProps(aiChatProps);
const emit = defineEmits(aiChatEmits);
const ns = useNamespace("ai-chat");
const { t } = useLocale();
const { themeStyle } = useComponentTheme("ai-chat", props.themeOverrides);
const virtualScrollEnabled = computed(() => props.virtualScroll && props.messages.length > 50);
const { visibleItems, totalHeight, offsetY, startIndex, onScroll, scrollToIndex, containerRef } = useVirtualScroll({
  items: computed(() => props.messages),
  itemHeight: props.estimatedItemHeight,
  containerHeight: props.virtualHeight,
  overscan: 5
});
const contentRef = containerRef;
const scrollToBottom = () => {
  nextTick(() => {
    if (virtualScrollEnabled.value && props.messages.length > 0) {
      scrollToIndex(props.messages.length - 1);
    } else if (contentRef.value) {
      contentRef.value.scrollTop = contentRef.value.scrollHeight;
    }
  });
};
watch(() => props.messages, scrollToBottom, { deep: true });
watch(() => props.loading, scrollToBottom);
const handleSend = (text) => {
  emit("send", text);
};
const handleClear = () => {
  emit("update:messages", []);
  emit("clear");
};
</script>

<template>
  <div :class="ns.b()" :style="themeStyle">
    <!-- Header Tools (optional) -->
    <div :class="ns.e('header')" v-if="$slots.header || props.messages.length > 0">
      <slot name="header">
        <div :class="ns.e('header-tools')">
          <YhButton
            v-if="props.messages.length > 0"
            size="small"
            text
            :class="ns.e('clear-btn')"
            @click="handleClear"
          >
            <template #icon>
              <YhIcon name="delete" />
            </template>
            {{ t('common.clear') }}
          </YhButton>
        </div>
      </slot>
    </div>

    <!-- Messages List -->
    <div
      :class="ns.e('content')"
      ref="containerRef"
      :style="virtualScrollEnabled ? {
  height: props.virtualHeight + 'px',
  overflow: 'auto'
} : {}"
      @scroll="virtualScrollEnabled ? onScroll($event) : void 0"
    >
      <div
        v-if="props.messages.length === 0 && props.suggestions.length > 0"
        :class="ns.e('suggestions')"
      >
        <YhButton
          v-for="(suggestion, idx) in props.suggestions"
          :key="idx"
          plain
          round
          @click="handleSend(suggestion)"
        >
          {{ suggestion }}
        </YhButton>
      </div>

      <!-- Virtual Scroll Mode -->
      <template v-if="virtualScrollEnabled">
        <div :style="{
  height: totalHeight + 'px',
  position: 'relative'
}">
          <div :style="{
  transform: `translateY(${offsetY}px)`
}">
            <template v-for="(msg, index) in visibleItems" :key="msg.id || startIndex + index">
              <slot name="message" :message="msg" :index="startIndex + index">
                <YhAiBubble
                  :content="msg.content"
                  :role="msg.role"
                  :loading="msg.status === 'generating' || msg.status === 'loading'"
                  :variant="msg.role === 'assistant' ? 'borderless' : 'filled'"
                  :time="msg.time"
                  :markdown="true"
                />
              </slot>
            </template>
          </div>
        </div>
      </template>

      <!-- Normal Mode -->
      <template v-else>
        <template v-for="(msg, index) in props.messages" :key="msg.id || index">
          <slot name="message" :message="msg" :index="index">
            <!-- We use the powerful markdown rendering by default on the bubbles inside AiChat -->
            <YhAiBubble
              :content="msg.content"
              :role="msg.role"
              :loading="msg.status === 'generating' || msg.status === 'loading'"
              :variant="msg.role === 'assistant' ? 'borderless' : 'filled'"
              :time="msg.time"
              :markdown="true"
            />
          </slot>
        </template>
      </template>

      <!-- Loading Placeholder -->
      <slot
        name="loading"
        v-if="props.loading && (!props.messages.length || props.messages[props.messages.length - 1].role !== 'assistant' || props.messages[props.messages.length - 1].status !== 'generating' && props.messages[props.messages.length - 1].status !== 'loading')"
      >
        <YhAiBubble role="assistant" loading typing variant="borderless" />
      </slot>
    </div>

    <!-- Footer Input Bar -->
    <div :class="ns.e('footer')">
      <slot name="sender">
        <YhAiSender :loading="props.loading" @send="handleSend" />
      </slot>
    </div>
  </div>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-ai-chat {
  --yh-ai-chat-bg: var(--yh-bg-color);
  --yh-ai-chat-header-bg: var(--yh-bg-color-page);
  --yh-ai-chat-footer-bg: var(--yh-bg-color);
  display: flex;
  flex-direction: column;
  height: 100%;
  position: relative;
  background-color: var(--yh-ai-chat-bg);
}
.yh-ai-chat__header {
  padding: var(--yh-spacing-sm) var(--yh-spacing-lg);
  border-bottom: 1px solid var(--yh-border-color-light);
  display: flex;
  justify-content: flex-end;
  align-items: center;
  background-color: var(--yh-ai-chat-header-bg);
}

.yh-ai-chat__header-tools {
  display: flex;
  gap: var(--yh-spacing-sm);
}

.yh-ai-chat__clear-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  font-size: 12px;
  line-height: 1;
  white-space: nowrap;
  color: var(--yh-text-color-secondary);
  background: transparent;
  border: none;
  box-shadow: none;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.yh-ai-chat__clear-btn .yh-icon {
  font-size: 14px;
  color: inherit;
}
.yh-ai-chat__clear-btn:hover {
  color: var(--yh-text-color-primary);
  background-color: var(--yh-fill-color-light);
  border-radius: 999px;
}

.yh-ai-chat__content {
  flex: 1;
  overflow-y: auto;
  padding: var(--yh-spacing-lg);
  scroll-behavior: smooth;
}
.yh-ai-chat__content::-webkit-scrollbar {
  width: 6px;
}
.yh-ai-chat__content::-webkit-scrollbar-thumb {
  background-color: var(--yh-scrollbar-thumb-color);
  border-radius: 3px;
}

.yh-ai-chat__suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--yh-spacing-sm);
  margin-bottom: var(--yh-spacing-lg);
  justify-content: center;
  margin-top: 10vh;
}

.yh-ai-chat__footer {
  padding: var(--yh-spacing-lg);
  background-color: var(--yh-ai-chat-footer-bg);
  border-top: 1px solid var(--yh-border-color-light);
}
</style>
