<template>
  <div class="chat-input-container" :class="{ 'is-focused': isFocused, 'is-expanded': isExpanded }">
    <!-- 输入区域 -->
    <div class="input-area">
      <!-- 左侧功能按钮 -->
      <div class="input-actions left">
        <StackedCards :cards="attachments" :supports-files="supports_files" :supports-vision="supports_vision"
          @remove="removeAttachment" @add-upload="triggerUploadInput" />

        <!-- 隐藏的文件输入框 -->
        <input
          ref="uploadInputRef"
          type="file"
          :accept="uploadAccept"
          multiple
          hidden
          @change="handleUploadSelect"
        />
      </div>

      <!-- 文本输入框 -->
      <div class="textarea-wrapper">
        <textarea ref="textareaRef" v-model="inputText" :placeholder="placeholder" :rows="1"
          @beforeinput="handleBeforeInput" @input="autoResize" @focus="isFocused = true" @blur="isFocused = false"
          @keydown="handleKeydown" @paste="handlePaste" />
      </div>


    </div>

    <!-- 底部工具栏 -->
    <div class="input-toolbar">
      <div class="toolbar-left">
        <!-- 展开/收起 -->
        <!-- <button class="toolbar-btn" title="展开输入框" @click="toggleExpand">
          <Maximize2 v-if="!isExpanded" :size="16" />
          <Minimize2 v-else :size="16" />
        </button> -->
        <!-- 深度思考开关 -->
        <button class="toolbar-btn"
          :class="{ active: isDeepThinking, disabled: isForceDeepThinkingModel || !supports_thinking }"
          :disabled="isForceDeepThinkingModel || !supports_thinking"
          :title="isForceDeepThinkingModel ? '当前模型强制开启深度思考' : (supports_thinking ? '深度思考' : '当前模型不支持深度思考')"
          @click="!isForceDeepThinkingModel && supports_thinking && toggleDeepThink()">
          <DeepThinkingIcon :size="16" />
          <span>深度思考</span>
        </button>

        <!-- 深度搜索开关 -->
        <button class="toolbar-btn" :class="{ active: isDeepSearch, disabled: !supports_web_search }"
          :disabled="!supports_web_search" :title="supports_web_search ? '深度搜索' : '当前模型不支持联网搜索'"
          @click="supports_web_search && toggleDeepSearch()">
          <DeepSearchIcon :size="16" />
          <span>深度搜索</span>
        </button>

        <!-- 联网搜索开关 -->
        <button class="toolbar-btn" :class="{ active: isWebSearch, disabled: !supports_web_search }"
          :disabled="!supports_web_search" :title="supports_web_search ? '联网搜索' : '当前模型不支持联网搜索'"
          @click="supports_web_search && toggleWebSearch()">
          <WebSearchIcon :size="16" />
          <span>联网搜索</span>
        </button>
      </div>
      <!-- 右侧功能按钮 -->
      <div class="input-actions right">
        <!-- 发送/停止按钮 -->
        <button v-if="isStreaming" class="action-btn stop" title="停止生成" @click="$emit('stop')">
          <StopIcon />
        </button>
        <button v-else class="action-btn send" :class="{ active: canSend, loading: isProcessingAttachments }"
          :disabled="!canSend" :title="isProcessingAttachments ? '附件处理中...' : '发送消息 (Ctrl+Enter)'" @click="handleSend">
          <LoadingIcon v-if="isProcessingAttachments" class="animate-spin" />
          <SendIcon v-else :size="20" />
        </button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted } from "vue";
import { generateId } from "@/utils/helpers";
import type { Attachment } from "@/types/chat";
import { chatApi } from "@/services/api";
import { useAuthStore } from "@/stores/auth";
import { useSettingsStore } from "@/stores/settings";
import StackedCards from "@/components/ui/StackedCards.vue";
import DeepThinkingIcon from "../icons/custom/DeepThinkingIcon.vue";
import DeepSearchIcon from "../icons/custom/DeepSearchIcon.vue";
import WebSearchIcon from "../icons/custom/WebSearchIcon.vue";
import SendIcon from "../icons/custom/SendIcon.vue";
import StopIcon from "../icons/custom/StopIcon.vue";
import LoadingIcon from "../icons/custom/LoadingIcon.vue";

interface AttachmentWithProgress extends Attachment {
  uploading?: boolean;
  progress?: number;
  deleting?: boolean;
}

const props = withDefaults(
  defineProps<{
    placeholder?: string;
    isStreaming?: boolean;
    sendOnEnter?: boolean;
    maxChars?: number;
    disabled?: boolean;
    // 模型能力
    supports_thinking?: boolean;
    supports_web_search?: boolean;
    supports_vision?: boolean;
    supports_files?: boolean;
  }>(),
  {
    placeholder: "输入你的问题...",
    isStreaming: false,
    sendOnEnter: false,
    maxChars: 10000,
    disabled: false,
    // 默认全部支持
    supports_thinking: true,
    supports_web_search: true,
    supports_vision: true,
    supports_files: true,
  },
);

// 强制深度思考的模型列表（这些模型默认开启深度思考且不可关闭）
const FORCE_DEEP_THINKING_MODELS = ["deepseek-reasoner", "glm-z1-flash"];

// 判断当前模型是否强制开启深度思考
const isForceDeepThinkingModel = computed(() => {
  return FORCE_DEEP_THINKING_MODELS.includes(modelName.value.toLowerCase());
});

const emit = defineEmits<{
  send: [
    text: string,
    attachments: Attachment[],
    options: { deepSearch: boolean; webSearch: boolean; deepThinking: boolean },
  ];
  stop: [];
}>();

// 响应式状态
const authStore = useAuthStore();
const settingsStore = useSettingsStore();
const modelName = computed(() => settingsStore.settings.defaultModel);

const inputText = ref("");
const attachments = ref<AttachmentWithProgress[]>([]);
const isFocused = ref(false);
const isExpanded = ref(false);
const isDeepSearch = ref(
  JSON.parse(localStorage.getItem("isDeepSearch") || "false"),
);
const isDeepThinking = ref(
  JSON.parse(localStorage.getItem("isDeepThinking") || "false"),
);
const isWebSearch = ref(
  JSON.parse(localStorage.getItem("isWebSearch") || "false"),
);
// DOM引用
const textareaRef = ref<HTMLTextAreaElement | null>(null);
const uploadInputRef = ref<HTMLInputElement | null>(null);

// toast 节流
let lastToastTime = 0;
const toastThrottleMs = 2000;

function showThrottledToast(message: string, type: "error" = "error") {
  const now = Date.now();
  if (now - lastToastTime >= toastThrottleMs) {
    lastToastTime = now;
    window.$toast?.(message, type);
  }
}

// 计算属性
const charCount = computed(() => inputText.value.length);
const isProcessingAttachments = computed(() =>
  attachments.value.some((a) => a.uploading || a.deleting),
);
const textFileAccept =
  ".txt,.md,.markdown,.pdf,.doc,.docx,.rtf,.csv,.tsv,.json,.xml,.html,.htm,.yaml,.yml,.log,.ini,.conf,.sql,.js,.ts,.jsx,.tsx,.py,.java,.c,.cpp,.h,.hpp,.go,.rs,.sh";
const uploadAccept = computed(() => {
  if (props.supports_vision && props.supports_files) {
    return `image/*,${textFileAccept}`;
  }
  if (props.supports_vision) {
    return "image/*";
  }
  if (props.supports_files) {
    return textFileAccept;
  }
  return "";
});

function getFileExt(fileName: string) {
  const idx = fileName.lastIndexOf(".");
  if (idx === -1) return "";
  return fileName.slice(idx).toLowerCase();
}

function getUploadTypeByModel(file: File): "image" | "file" | null {
  const isImage =
    file.type.startsWith("image/") ||
    [".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".svg", ".heic"].includes(
      getFileExt(file.name),
    );

  if (isImage) {
    return props.supports_vision ? "image" : null;
  }

  return props.supports_files ? "file" : null;
}
const canSend = computed(() => {
  return (
    (inputText.value.trim().length > 0 || attachments.value.length > 0) &&
    !props.disabled &&
    charCount.value <= props.maxChars &&
    !isProcessingAttachments.value
  );
});

// 自动调整高度
function autoResize() {
  const textarea = textareaRef.value;
  if (!textarea) return;

  textarea.style.height = "auto";
  const maxHeight = isExpanded.value ? 400 : 116;
  // 增加1px是为了避免滚动条出现
  textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight) + 1}px`;
}

// 处理输入前事件，限制字数
function handleBeforeInput(event: InputEvent) {
  // 如果不是插入文本的操作（如删除、退格等），允许
  if (!event.data) return;

  // 检查输入后是否会超过限制
  const currentLength = inputText.value.length;
  const insertLength = event.data?.length || 0;
  const selectionStart =
    (event.target as HTMLTextAreaElement).selectionStart || 0;
  const selectionEnd = (event.target as HTMLTextAreaElement).selectionEnd || 0;
  const selectedLength = selectionEnd - selectionStart;

  // 计算输入后的长度
  const newLength = currentLength - selectedLength + insertLength;

  if (newLength > props.maxChars) {
    event.preventDefault();
    showThrottledToast(`已超${props.maxChars}字上限，请删除部分内容`);
  }
}

// 处理键盘事件
function handleKeydown(event: KeyboardEvent) {
  // Ctrl+Enter 或 Cmd+Enter 发送
  if ((event.ctrlKey || event.metaKey) && event.key === "Enter") {
    event.preventDefault();
    handleSend();
    return;
  }

  // Enter 发送（如果开启了这个选项且没有按 Shift）
  if (props.sendOnEnter && event.key === "Enter" && !event.shiftKey) {
    event.preventDefault();
    handleSend();
    return;
  }
}

// 发送消息
function handleSend() {
  if (!canSend.value) return;

  emit("send", inputText.value.trim(), [...attachments.value], {
    deepSearch: isDeepSearch.value,
    webSearch: isWebSearch.value,
    deepThinking: isDeepThinking.value,
  });

  // 重置状态
  inputText.value = "";
  attachments.value = [];
  // isDeepSearch.value = false;
  // isWebSearch.value = false;
  // isDeepThinking.value = false;

  nextTick(() => {
    autoResize();
  });
}

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

  // 检查粘贴文本是否会超过字数限制
  const text = event.clipboardData?.getData("text");
  if (text) {
    const textarea = event.target as HTMLTextAreaElement;
    const selectionStart = textarea.selectionStart || 0;
    const selectionEnd = textarea.selectionEnd || 0;
    const selectedLength = selectionEnd - selectionStart;
    const newLength = inputText.value.length - selectedLength + text.length;

    if (newLength > props.maxChars) {
      event.preventDefault();
      showThrottledToast(`已超${props.maxChars}字上限，请删除部分内容`);
      return;
    }
  }

  for (const item of items) {
    if (item.type.startsWith("image/")) {
      const file = item.getAsFile();
      if (file) {
        const uploadType = getUploadTypeByModel(file);
        if (uploadType === "image") {
          event.preventDefault();
          await addFileAsAttachment(file, uploadType);
        } else {
          event.preventDefault();
          showThrottledToast("当前模型不支持上传图片");
        }
      }
    }
  }
}

function triggerUploadInput() {
  if (!props.supports_vision && !props.supports_files) {
    showThrottledToast("当前模型不支持上传附件");
    return;
  }
  uploadInputRef.value?.click();
}

// 处理上传选择
async function handleUploadSelect(event: Event) {
  const input = event.target as HTMLInputElement;
  const files = input.files;
  if (!files) return;

  for (const file of files) {
    const uploadType = getUploadTypeByModel(file);
    if (!uploadType) {
      showThrottledToast(
        file.type.startsWith("image/")
          ? "当前模型不支持上传图片"
          : "当前模型不支持上传附件文件",
      );
      continue;
    }
    await addFileAsAttachment(file, uploadType);
  }

  input.value = "";
}

// 添加文件作为附件
async function addFileAsAttachment(
  file: File,
  type: "image" | "file" | "video",
) {
  // 检查认证状态
  if (!authStore.isAuthenticated) {
    window.$toast?.("请先登录", "error");
    return;
  }

  const id = generateId();

  // 创建本地预览URL
  const url = URL.createObjectURL(file);

  const attachment: AttachmentWithProgress = {
    id,
    name: file.name,
    type,
    url,
    size: file.size,
    mimeType: file.type,
    uploading: true,
    progress: 0,
  };

  attachments.value.push(attachment);

  // 实际上传文件到服务器
  await uploadFileToServer(id, file);
}

// 上传文件到服务器
async function uploadFileToServer(id: string, file: File) {
  try {
    const uploadResult = await chatApi.uploadFile(file);

    const attachment = attachments.value.find((a) => a.id === id);
    if (attachment) {
      // 替换本地预览URL为服务器返回的真实URL
      attachment.url = uploadResult.url;
      attachment.uploading = false;
      attachment.progress = 100;
    }

    // 显示上传成功提示
    window.$toast && window.$toast("文件上传成功", "success");
  } catch (error) {
    console.error("文件上传失败:", error);

    const attachment = attachments.value.find((a) => a.id === id);
    if (attachment) {
      attachment.uploading = false;
      // 设置错误状态或者移除附件
      removeAttachment(id);
    }

    // 显示错误提示
    window.$toast && window.$toast("文件上传失败，请重试", "error");
  }
}

// 移除附件
async function removeAttachment(id: string | number) {
  const targetId = String(id);
  const index = attachments.value.findIndex((a) => a.id === targetId);
  if (index === -1) return;

  const attachment = attachments.value[index];
  let deletedFromOss = false;

  // 如果已上传到 OSS（不是本地 blob URL），则从 OSS 删除
  if (attachment.url && !attachment.url.startsWith("blob:")) {
    try {
      attachment.deleting = true;
      await nextTick();
      await chatApi.deleteAttachment(attachment.url);
      deletedFromOss = true;
    } catch (error) {
      console.error("删除 OSS 文件失败:", error);
      // 即使删除失败也继续移除本地引用
    } finally {
      attachment.deleting = false;
    }
  }

  // 释放 blob URL（如果是本地的）
  if (attachment.url.startsWith("blob:")) {
    URL.revokeObjectURL(attachment.url);
  }

  attachments.value.splice(index, 1);

  if (deletedFromOss) {
    window.$toast?.("OSS 文件删除成功", "success");
  }
}

// 切换功能（深度搜索与联网搜索互斥）
function toggleDeepSearch() {
  isDeepSearch.value = !isDeepSearch.value;
  if (isDeepSearch.value) {
    isWebSearch.value = false;
    localStorage.setItem("isWebSearch", "false");
  }
  localStorage.setItem("isDeepSearch", String(isDeepSearch.value));
}

function toggleDeepThink() {
  isDeepThinking.value = !isDeepThinking.value;
  localStorage.setItem("isDeepThinking", String(isDeepThinking.value));
}

function toggleWebSearch() {
  isWebSearch.value = !isWebSearch.value;
  if (isWebSearch.value) {
    isDeepSearch.value = false;
    localStorage.setItem("isDeepSearch", "false");
  }
  localStorage.setItem("isWebSearch", String(isWebSearch.value));
}

// 暴露方法给父组件
function focus() {
  textareaRef.value?.focus();
}

function clear() {
  inputText.value = "";
  attachments.value = [];
  nextTick(() => {
    autoResize();
  });
}

defineExpose({
  focus,
  clear,
  attachments,
  removeAttachment,
});

// 监听文本变化，自动调整高度
watch(inputText, () => {
  nextTick(() => {
    autoResize();
  });
});
// 监听模型变化，重置选项功能
watch(
  () => settingsStore.settings.defaultModel,
  (newModel) => {
    // 如果是强制深度思考的模型，自动开启深度思考
    if (FORCE_DEEP_THINKING_MODELS.includes(newModel.toLowerCase())) {
      isDeepThinking.value = true;
      localStorage.setItem("isDeepThinking", "true");
    } else {
      isDeepThinking.value = false;
      localStorage.setItem("isDeepThinking", "false");
    }
    // 重置搜索相关选项
    isDeepSearch.value = false;
    isWebSearch.value = false;
    localStorage.setItem("isDeepSearch", "false");
    localStorage.setItem("isWebSearch", "false");
  },
);

onMounted(() => {
  autoResize();
});
</script>

<style lang="scss" scoped>
.chat-input-container {
  background: #F8F9FA;
  // border: 2px solid #e2e8f0;
  height: 200px;
  border-radius: 20px;
  padding: 20px;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 12px;
  border-color: #374151;

  // &.is-focused {
  //   border-color: #3b82f6;
  //   box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1);
  // }

  &.is-expanded {
    .textarea-wrapper textarea {
      min-height: 200px;
    }
  }
}

.input-area {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  min-height: 0;
  gap: 8px;
}

.input-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-bottom: 4px;
  min-width: 0;

  &.left {
    flex-shrink: 0;
  }

  &.right {
    flex-shrink: 0;
  }
}

.action-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: none;
  border-radius: 50px;
  background: transparent;
  color: #6b7280;
  cursor: pointer;
  transition: all 0.2s ease;

  &:hover {
    background: #9f9fa05c;
    color: #374151;

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

  &.disabled,
  &:disabled {
    opacity: 0.4;
    cursor: not-allowed;

    // &:hover {
    //   background: transparent;
    //   color: #6b7280;
    // }
  }

  &.send {
    background: rgba(0, 15, 51, 0.20);
    color: #9ca3af;

    .dark & {
      background: #374151;
    }

    &.active {
      background: #000E32;
      color: white;

      &:hover {
        transform: scale(1.05);
        // box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
      }
    }

    &.loading {
      background: #000F33;
      color: white;
      cursor: wait;
    }

    &:disabled {
      background: rgba(0, 15, 51, 0.20);
      cursor: not-allowed;
      opacity: 0.6;
    }
  }

  &.stop {
    background: #000F33;
    color: white;

    &:hover {
      transform: scale(1.05);
    }
  }
}

.textarea-wrapper {
  flex: 1;
  min-width: 0;
  min-height: 0;

  textarea {
    width: 100%;
    min-height: 25px;
    max-height: 100%;
    overflow-y: auto;
    scrollbar-gutter: stable;
    padding: 8px 0;
    border: none;
    outline: none;
    background: transparent;
    font-family: inherit;
    font-size: 15px;
    line-height: 1.5;
    color: #1f2937;
    resize: none;

    .dark & {
      color: #f3f4f6;
    }

    &::placeholder {
      color: #9ca3af;
    }
  }
}

.input-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  // background: #fafbfc;

  .dark & {
    border-top-color: #2d2d3d;
    background: #181825;
  }
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 6px;
}

.toolbar-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 10px 15px;
  border-radius: 50px;
  background: var(---FFFFFF, #FFF);
  border: 1px solid transparent;
  color: var(--6-666666, #666);
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s ease;

  &:hover {
    background: #9f9fa05c;
    color: #374151;

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

  &.active {
    background: #DFE2E6;
    // border-color: rgba(59, 130, 246, 0.3);
    color: #000F33;

    svg {
      color: #000F33;
    }
  }

  &.disabled,
  &:disabled {
    opacity: 0.4;
    cursor: not-allowed;

    &:hover {
      background: transparent;
      color: #6b7280;
    }
  }
}

</style>
