<!-- 默认消息列表页 -->
<script setup lang="ts">
import type { FilesCardProps } from 'vue-element-plus-x/types/FilesCard';
import { ArrowLeftBold, ArrowRightBold, Loading } from '@element-plus/icons-vue';
import { useDebounceFn } from '@vueuse/core';
import { ElMessage } from 'element-plus';
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import ModelSelect from '@/components/ModelSelect/index.vue';
import WelecomeText from '@/components/WelecomeText/index.vue';
import Collapse from '@/layouts/components/Header/components/Collapse.vue';
import CreateChat from '@/layouts/components/Header/components/CreateChat.vue';
import { useUserStore } from '@/stores';
import { useFilesStore } from '@/stores/modules/files';
import { useSessionStore } from '@/stores/modules/session';

// Store 实例
const userStore = useUserStore();
const sessionStore = useSessionStore();
const filesStore = useFilesStore();

// 计算属性
const currentSession = computed(() => sessionStore.currentSession);

// 响应式数据
const senderValue = ref(''); // 输入框内容
const senderRef = ref(); // Sender 组件引用
const isSending = ref(false); // 发送状态标志

// 文件处理相关常量
const MAX_FILE_SIZE = 3 * 1024 * 1024;
const MAX_TOTAL_CONTENT_LENGTH = 150000;

/**
 * 防抖发送消息函数
 */
const debouncedSend = useDebounceFn(
  async () => {
    // 1. 验证输入
    if (!senderValue.value.trim()) {
      ElMessage.warning('消息内容不能为空');
      return;
    }

    // 2. 检查是否正在发送
    if (isSending.value) {
      ElMessage.warning('请等待上一条消息发送完成');
      return;
    }

    // 3. 准备发送数据
    const content = senderValue.value.trim();
    isSending.value = true;

    try {
      // 4. 保存到本地存储（可选，用于页面刷新后恢复）
      localStorage.setItem('chatContent', content);

      // 5. 创建会话
      await sessionStore.createSessionList({
        userId: userStore.userInfo?.userId as number,
        sessionContent: content,
        sessionTitle: content.slice(0, 10),
        remark: content.slice(0, 10),
      });

      // 6. 清空输入框
      senderValue.value = '';
    }
    catch (error: any) {
      console.error('发送消息失败:', error);
      ElMessage.error(error.message || '发送消息失败');
    }
    finally {
      // 7. 重置发送状态
      isSending.value = false;
    }
  },
  800, // 防抖延迟
  { leading: true, trailing: false }, // 立即执行第一次，忽略后续快速点击
);

/**
 * 触发发送消息
 */
function handleSend() {
  debouncedSend();
}

/**
 * 删除文件卡片
 * @param _item 文件项
 * @param index 文件索引
 */
function handleDeleteCard(_item: FilesCardProps, index: number) {
  filesStore.deleteFileByIndex(index);
}

/**
 * 监听文件列表变化，自动展开/收起 Sender 头部
 */
watch(
  () => filesStore.filesList.length,
  (val) => {
    nextTick(() => {
      if (val > 0) {
        senderRef.value?.openHeader();
      }
      else {
        senderRef.value?.closeHeader();
      }
    });
  },
);

/**
 * 压缩图片
 */
function compressImage(file: File, maxWidth = 1024, maxHeight = 1024, quality = 0.8): Promise<Blob> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        let width = img.width;
        let height = img.height;

        if (width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height);
          width = width * ratio;
          height = height * ratio;
        }

        canvas.width = width;
        canvas.height = height;

        const ctx = canvas.getContext('2d')!;
        ctx.drawImage(img, 0, 0, width, height);

        canvas.toBlob(
          (blob) => {
            if (blob) {
              resolve(blob);
            }
            else {
              reject(new Error('压缩失败'));
            }
          },
          file.type,
          quality,
        );
      };
      img.onerror = reject;
      img.src = e.target?.result as string;
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

/**
 * 将 Blob 转换为 base64
 */
function blobToBase64(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      resolve(reader.result as string);
    };
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

/**
 * 处理粘贴事件
 */
async function handlePaste(event: ClipboardEvent) {
  const items = event.clipboardData?.items;
  if (!items)
    return;

  const files: File[] = [];
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (item.kind === 'file') {
      const file = item.getAsFile();
      if (file) {
        files.push(file);
      }
    }
  }

  if (files.length === 0)
    return;

  event.preventDefault();

  // 计算已有文件的总内容长度
  let totalContentLength = 0;
  filesStore.filesList.forEach((f) => {
    if (f.fileType === 'text' && f.fileContent) {
      totalContentLength += f.fileContent.length;
    }
    if (f.fileType === 'image' && f.base64) {
      totalContentLength += Math.floor(f.base64.length * 0.5);
    }
  });

  const arr: any[] = [];

  for (const file of files) {
    // 验证文件大小
    if (file.size > MAX_FILE_SIZE) {
      ElMessage.error(`文件 ${file.name} 超过 3MB 限制，已跳过`);
      continue;
    }

    const isImage = file.type.startsWith('image/');

    if (isImage) {
      try {
        const compressionLevels = [
          { maxWidth: 800, maxHeight: 800, quality: 0.6 },
          { maxWidth: 600, maxHeight: 600, quality: 0.5 },
          { maxWidth: 400, maxHeight: 400, quality: 0.4 },
        ];

        let compressedBlob: Blob | null = null;
        let base64 = '';

        for (const level of compressionLevels) {
          compressedBlob = await compressImage(file, level.maxWidth, level.maxHeight, level.quality);
          base64 = await blobToBase64(compressedBlob);

          const estimatedLength = Math.floor(base64.length * 0.5);
          if (totalContentLength + estimatedLength <= MAX_TOTAL_CONTENT_LENGTH) {
            totalContentLength += estimatedLength;
            break;
          }

          compressedBlob = null;
        }

        if (!compressedBlob) {
          ElMessage.error(`${file.name} 图片内容过大，请压缩后上传`);
          continue;
        }

        arr.push({
          uid: crypto.randomUUID(),
          name: file.name,
          fileSize: file.size,
          file,
          maxWidth: '200px',
          showDelIcon: true,
          imgPreview: true,
          imgVariant: 'square',
          url: base64,
          isUploaded: true,
          base64,
          fileType: 'image',
        });
      }
      catch (error) {
        console.error('处理图片失败:', error);
        ElMessage.error(`${file.name} 处理失败`);
      }
    }
    else {
      ElMessage.warning(`${file.name} 不支持粘贴，请使用上传按钮`);
    }
  }

  if (arr.length > 0) {
    filesStore.setFilesList([...filesStore.filesList, ...arr]);
    ElMessage.success(`已添加 ${arr.length} 个文件`);
  }
}

// 监听粘贴事件
onMounted(() => {
  document.addEventListener('paste', handlePaste);
});

onUnmounted(() => {
  document.removeEventListener('paste', handlePaste);
});
</script>

<template>
  <div class="chat-default">
    <!-- 头部导航栏 -->
    <div class="chat-header">
      <div class="header-content">
        <div class="header-left">
          <Collapse />
          <CreateChat />
        </div>
      </div>
    </div>

    <div class="chat-default-wrap">
      <!-- 欢迎文本 -->
      <WelecomeText />

      <!-- 消息发送器 -->
      <Sender
        ref="senderRef"
        v-model="senderValue"
        class="chat-default-sender"
        data-tour="chat-sender"
        :auto-size="{
          maxRows: 9,
          minRows: 3,
        }"
        variant="updown"
        clearable
        allow-speech
        :loading="isSending"
        @submit="handleSend"
      >
        <!-- 头部：文件附件区域 -->
        <template #header>
          <div class="sender-header">
            <Attachments
              :items="filesStore.filesList"
              :hide-upload="true"
              @delete-card="handleDeleteCard"
            >
              <!-- 左侧滚动按钮 -->
              <template #prev-button="{ show, onScrollLeft }">
                <div
                  v-if="show"
                  class="scroll-btn prev-btn"
                  @click="onScrollLeft"
                >
                  <el-icon>
                    <ArrowLeftBold />
                  </el-icon>
                </div>
              </template>

              <!-- 右侧滚动按钮 -->
              <template #next-button="{ show, onScrollRight }">
                <div
                  v-if="show"
                  class="scroll-btn next-btn"
                  @click="onScrollRight"
                >
                  <el-icon>
                    <ArrowRightBold />
                  </el-icon>
                </div>
              </template>
            </Attachments>
          </div>
        </template>

        <!-- 前缀：文件选择和模型选择 -->
        <template #prefix>
          <div class="sender-prefix">
            <FilesSelect />
            <ModelSelect />
          </div>
        </template>

        <!-- 后缀：发送加载动画 -->
        <template #suffix>
          <el-icon v-if="isSending" class="loading-icon">
            <Loading />
          </el-icon>
        </template>
      </Sender>
    </div>
  </div>
</template>

<style scoped lang="scss">
.chat-default {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 20px;

  .chat-header {
    width: 100%;
    //max-width: 1000px;
    height: 60px;
    display: flex;
    align-items: center;
    flex-shrink: 0;

    .header-content {
      width: 100%;
      display: flex;
      align-items: center;

      .header-left {
        display: flex;
        align-items: center;
        gap: 12px;
      }
    }
  }
}

.chat-default-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 800px;
  min-height: 450px;
  padding: 20px;
  box-sizing: border-box;

  .chat-default-sender {
    width: 100%;
    margin-top: 30px;
  }
}

.sender-header {
  padding: 12px 12px 0 12px;
}

.sender-prefix {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 8px;
  flex: none;
  width: fit-content;
  overflow: hidden;
}

.scroll-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.08);
  color: rgba(0, 0, 0, 0.4);
  background-color: #fff;
  font-size: 10px;
  cursor: pointer;
  z-index: 10;
  transition: all 0.2s ease;

  &:hover {
    background-color: #f3f4f6;
    border-color: rgba(0, 0, 0, 0.15);
    color: rgba(0, 0, 0, 0.6);
  }

  &.prev-btn {
    left: 8px;
  }

  &.next-btn {
    right: 8px;
  }
}

.loading-icon {
  margin-left: 8px;
  color: var(--el-color-primary);
  animation: rotating 2s linear infinite;
}

@keyframes rotating {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

// 响应式设计
@media (max-width: 768px) {
  .chat-default {
    padding: 0 12px;

    .chat-header {
      height: 50px;
    }
  }

  .chat-default-wrap {
    padding: 12px;
    min-height: calc(100vh - 120px);

    .chat-default-sender {
      margin-top: 20px;
    }
  }

  .sender-prefix {
    flex-wrap: wrap;
    gap: 6px;
  }
}
</style>
