<template>
  <div class="ai-3d-container">
    <!-- 左侧生成栏 -->
    <div class="left-panel">
      <div class="panel-header">
        <a-segmented
          v-model:value="inputType"
          :options="inputTypeOptions"
          block
        />
      </div>

      <div class="panel-content">
        <!-- 文生3D输入 -->
        <div v-if="inputType === 'text'" class="text-input-section">
          <div class="input-hint">
            请输入想要生成的内容，建议以单体为主。例如：一只棕色的猫雕塑，尾巴卷曲，卡通风格
          </div>
          <a-textarea
            v-model:value="textContent"
            placeholder="请输入描述..."
            :rows="6"
            :maxlength="150"
            show-count
            class="text-input"
          />
          <div class="sample-prompts">
            <ReloadOutlined class="refresh-icon" @click="refreshSamples" />
            <span
              v-for="(sample, index) in currentSamples"
              :key="index"
              class="sample-tag"
              @click="applySample(sample)"
            >
              {{ sample }}
            </span>
          </div>
        </div>

        <!-- 图生3D上传 -->
        <div v-else class="image-input-section">
          <div class="input-hint">
            上传一张参考图片，AI 将根据图片生成 3D 模型
          </div>
          <a-upload-dragger
            v-model:file-list="imageFileList"
            :before-upload="handleBeforeUpload"
            :max-count="1"
            accept="image/*"
            class="image-upload"
          >
            <p class="ant-upload-drag-icon">
              <PictureOutlined />
            </p>
            <p class="ant-upload-text">点击或拖拽图片到此处</p>
            <p class="ant-upload-hint">支持 JPG、PNG 格式</p>
          </a-upload-dragger>
        </div>
      </div>

      <div class="panel-footer">
        <a-button
          type="primary"
          size="large"
          block
          :loading="generating"
          :disabled="!canGenerate"
          @click="handleGenerate"
        >
          <template #icon><ThunderboltOutlined /></template>
          立即生成
        </a-button>
      </div>
    </div>

    <!-- 右侧内容区 -->
    <div class="right-panel">
      <!-- 介绍区 -->
      <div class="intro-section">
        <h1 class="intro-title">用一句话、一张图，生成你的 3D 世界</h1>
        <div class="intro-features">
          <div class="feature-item">
            <span class="feature-icon">✨</span>
            <span class="feature-text"
              >AI 智能建模：输入文字描述或上传参考图，自动生成 3D 模型</span
            >
          </div>
          <div class="feature-item">
            <span class="feature-icon">👁</span>
            <span class="feature-text"
              >在线实时预览：支持模型旋转、缩放与查看细节</span
            >
          </div>
          <div class="feature-item">
            <span class="feature-icon">📁</span>
            <span class="feature-text"
              >作品统一管理：所有建模成果自动保存至个人作品库</span
            >
          </div>
          <div class="feature-item">
            <span class="feature-icon">🔄</span>
            <span class="feature-text"
              >持续创作迭代：支持基于已有作品再次生成与优化</span
            >
          </div>
        </div>
        <a class="intro-action" @click="focusInput"> 立即开始建模 → </a>
        <p class="intro-subtitle">从一个想法开始，让 3D 创作变得更简单</p>
      </div>

      <!-- 创作历史区 -->
      <div class="history-section">
        <div class="history-header">
          <h2 class="history-title">创作历史</h2>
          <a class="view-all" @click="showAllHistory = true">查看全部 ></a>
        </div>

        <div v-if="historyLoading" class="history-loading">
          <a-spin />
        </div>

        <div v-else-if="historyList.length === 0" class="history-empty">
          <a-empty description="暂无创作记录，开始你的第一次创作吧" />
        </div>

        <div v-else class="history-grid">
          <div
            v-for="task in historyList"
            :key="task.id"
            class="history-card"
            @click="handleViewTask(task)"
          >
            <div class="card-preview">
              <img
                v-if="task.status === 'completed' && task.previewUrl"
                :src="getPreviewUrl(task)"
                alt="预览"
                class="preview-image"
              />
              <div
                v-else-if="
                  task.status === 'processing' || task.status === 'pending'
                "
                class="preview-loading"
              >
                <LoadingOutlined spin />
                <span>生成中...</span>
              </div>
              <div
                v-else-if="
                  task.status === 'failed' || task.status === 'timeout'
                "
                class="preview-failed"
              >
                <ExclamationCircleOutlined />
                <span>{{
                  task.status === "timeout" ? "已超时" : "生成失败"
                }}</span>
              </div>
              <div v-else class="preview-placeholder">
                <FileImageOutlined />
              </div>
            </div>
            <div class="card-info">
              <div class="card-desc" :title="task.inputContent">
                {{ task.inputContent }}
              </div>
              <div class="card-meta">
                <span class="card-time">{{ formatTime(task.createTime) }}</span>
                <div class="card-actions" @click.stop>
                  <a-tooltip v-if="task.status === 'completed'" title="预览">
                    <EyeOutlined
                      class="action-icon"
                      @click="handlePreview(task)"
                    />
                  </a-tooltip>
                  <a-tooltip
                    v-if="['failed', 'timeout'].includes(task.status)"
                    title="重试"
                  >
                    <ReloadOutlined
                      class="action-icon"
                      :class="{ disabled: task.retryCount >= 3 }"
                      @click="handleRetry(task)"
                    />
                  </a-tooltip>
                  <a-tooltip title="删除">
                    <DeleteOutlined
                      class="action-icon danger"
                      @click="handleDelete(task)"
                    />
                  </a-tooltip>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 全部历史记录抽屉 -->
    <a-drawer
      v-model:open="showAllHistory"
      title="全部创作历史"
      placement="right"
      width="600px"
    >
      <a-list
        :data-source="allHistoryList"
        :loading="allHistoryLoading"
        :pagination="pagination"
      >
        <template #renderItem="{ item }">
          <a-list-item>
            <a-list-item-meta>
              <template #avatar>
                <div class="list-preview">
                  <img
                    v-if="item.status === 'completed' && item.previewUrl"
                    :src="getPreviewUrl(item)"
                    alt="预览"
                  />
                  <div v-else class="list-preview-placeholder">
                    <LoadingOutlined
                      v-if="['pending', 'processing'].includes(item.status)"
                      spin
                    />
                    <ExclamationCircleOutlined
                      v-else-if="['failed', 'timeout'].includes(item.status)"
                    />
                    <FileImageOutlined v-else />
                  </div>
                </div>
              </template>
              <template #title>
                <span class="list-desc">{{ item.inputContent }}</span>
              </template>
              <template #description>
                <div class="list-meta">
                  <a-tag :color="getStatusColor(item.status)">{{
                    getStatusText(item.status)
                  }}</a-tag>
                  <span>{{ formatTime(item.createTime) }}</span>
                </div>
              </template>
            </a-list-item-meta>
            <template #actions>
              <a v-if="item.status === 'completed'" @click="handlePreview(item)"
                >预览</a
              >
              <a
                v-if="
                  ['failed', 'timeout'].includes(item.status) &&
                  item.retryCount < 3
                "
                @click="handleRetry(item)"
                >重试</a
              >
              <a class="danger-link" @click="handleDelete(item)">删除</a>
            </template>
          </a-list-item>
        </template>
      </a-list>
    </a-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from "vue"
import { message, Modal } from "ant-design-vue"
import {
  ReloadOutlined,
  PictureOutlined,
  ThunderboltOutlined,
  LoadingOutlined,
  ExclamationCircleOutlined,
  FileImageOutlined,
  EyeOutlined,
  DeleteOutlined,
} from "@ant-design/icons-vue"
import type { UploadFile } from "ant-design-vue"
import {
  createAI3DTask,
  getAI3DTasks,
  getAI3DTask,
  retryAI3DTask,
  deleteAI3DTask,
  type AI3DTask,
} from "@/api/ai-3d"
import { uploadFile } from "@/api/upload"
import dayjs from "dayjs"

// 输入类型选项
const inputTypeOptions = [
  { label: "文生3D", value: "text" },
  { label: "图生3D", value: "image" },
]

// 示例提示词
const samplePrompts = [
  ["啄木鸟", "尖锐的嘴", "金黄色"],
  ["可爱的猫咪", "卡通风格", "蓝色眼睛"],
  ["机器人", "金属质感", "未来风格"],
  ["中式花瓶", "青花瓷", "精致纹理"],
  ["小恐龙", "Q版造型", "绿色皮肤"],
  ["宇航员", "太空服", "写实风格"],
]

// 状态
const inputType = ref<"text" | "image">("text")
const textContent = ref("")
const imageFileList = ref<UploadFile[]>()
const imageUrl = ref("")
const generating = ref(false)
const currentSampleIndex = ref(0)

// 历史记录
const historyList = ref<AI3DTask[]>([])
const historyLoading = ref(false)
const showAllHistory = ref(false)
const allHistoryList = ref<AI3DTask[]>([])
const allHistoryLoading = ref(false)
const allHistoryTotal = ref(0)
const allHistoryPage = ref(1)

// 轮询定时器
let pollingTimer: number | null = null

// 计算属性
const currentSamples = computed(() => samplePrompts[currentSampleIndex.value])

const canGenerate = computed(() => {
  if (inputType.value === "text") {
    return textContent.value.trim().length > 0
  } else {
    return imageUrl.value.length > 0
  }
})

const pagination = computed(() => ({
  current: allHistoryPage.value,
  pageSize: 10,
  total: allHistoryTotal.value,
  onChange: (page: number) => {
    allHistoryPage.value = page
    fetchAllHistory()
  },
}))

// 刷新示例
const refreshSamples = () => {
  currentSampleIndex.value =
    (currentSampleIndex.value + 1) % samplePrompts.length
}

// 应用示例
const applySample = (sample: string) => {
  if (textContent.value) {
    textContent.value += "，" + sample
  } else {
    textContent.value = sample
  }
}

// 聚焦输入
const focusInput = () => {
  // 滚动到左侧面板
}

// 图片上传前处理
const handleBeforeUpload = async (file: File) => {
  const isImage = file.type.startsWith("image/")
  if (!isImage) {
    message.error("只能上传图片文件")
    return false
  }

  const isLt10M = file.size / 1024 / 1024 < 10
  if (!isLt10M) {
    message.error("图片大小不能超过 10MB")
    return false
  }

  // 上传图片
  try {
    const result = await uploadFile(file)
    imageUrl.value = result.url
    message.success("图片上传成功")
  } catch (error) {
    message.error("图片上传失败")
    return false
  }

  return false // 阻止默认上传行为
}

// 生成3D模型
const handleGenerate = async () => {
  if (!canGenerate.value) return

  generating.value = true
  try {
    const content =
      inputType.value === "text" ? textContent.value.trim() : imageUrl.value

    await createAI3DTask({
      inputType: inputType.value,
      inputContent: content,
    })

    message.success("任务已提交，请等待生成完成")

    // 清空输入
    if (inputType.value === "text") {
      textContent.value = ""
    } else {
      imageFileList.value = []
      imageUrl.value = ""
    }

    // 刷新历史记录
    fetchHistory()

    // 开始轮询
    startPolling()
  } catch (error: any) {
    message.error(error.response?.data?.message || "提交失败，请重试")
  } finally {
    generating.value = false
  }
}

// 获取历史记录（最近6条）
const fetchHistory = async () => {
  historyLoading.value = true
  try {
    const res = await getAI3DTasks({ page: 1, pageSize: 6 })
    historyList.value = res.list || []
  } catch (error) {
    console.error("获取历史记录失败:", error)
  } finally {
    historyLoading.value = false
  }
}

// 获取全部历史记录
const fetchAllHistory = async () => {
  allHistoryLoading.value = true
  try {
    const res = await getAI3DTasks({ page: allHistoryPage.value, pageSize: 10 })
    allHistoryList.value = res.list || []
    allHistoryTotal.value = res.total || 0
  } catch (error) {
    console.error("获取全部历史记录失败:", error)
  } finally {
    allHistoryLoading.value = false
  }
}

// 开始轮询（检查处理中的任务）
const startPolling = () => {
  if (pollingTimer) return

  pollingTimer = window.setInterval(async () => {
    const processingTasks = historyList.value.filter(
      (t) => t.status === "pending" || t.status === "processing"
    )

    if (processingTasks.length === 0) {
      stopPolling()
      return
    }

    // 刷新历史记录
    await fetchHistory()
  }, 3000)
}

// 停止轮询
const stopPolling = () => {
  if (pollingTimer) {
    clearInterval(pollingTimer)
    pollingTimer = null
  }
}

// 预览3D模型
const handlePreview = (task: AI3DTask) => {
  if (task.resultUrl) {
    const viewerUrl = `/model-viewer?url=${encodeURIComponent(task.resultUrl)}`
    window.open(viewerUrl, "_blank")
  }
}

// 查看任务详情
const handleViewTask = (task: AI3DTask) => {
  if (task.status === "completed") {
    handlePreview(task)
  }
}

// 重试任务
const handleRetry = async (task: AI3DTask) => {
  if (task.retryCount >= 3) {
    message.warning("已达到最大重试次数，请创建新任务")
    return
  }

  try {
    await retryAI3DTask(task.id)
    message.success("重试已提交")
    fetchHistory()
    startPolling()
  } catch (error: any) {
    message.error(error.response?.data?.message || "重试失败")
  }
}

// 删除任务
const handleDelete = (task: AI3DTask) => {
  Modal.confirm({
    title: "确认删除",
    content: "确定要删除这条创作记录吗？",
    okText: "删除",
    okType: "danger",
    cancelText: "取消",
    async onOk() {
      try {
        await deleteAI3DTask(task.id)
        message.success("删除成功")
        fetchHistory()
        if (showAllHistory.value) {
          fetchAllHistory()
        }
      } catch (error) {
        message.error("删除失败")
      }
    },
  })
}

// 获取预览图URL
const getPreviewUrl = (task: AI3DTask) => {
  if (task.previewUrl) {
    return task.previewUrl.startsWith("http")
      ? task.previewUrl
      : task.previewUrl
  }
  return ""
}

// 获取状态颜色
const getStatusColor = (status: string) => {
  const colors: Record<string, string> = {
    pending: "default",
    processing: "processing",
    completed: "success",
    failed: "error",
    timeout: "warning",
  }
  return colors[status] || "default"
}

// 获取状态文本
const getStatusText = (status: string) => {
  const texts: Record<string, string> = {
    pending: "等待中",
    processing: "生成中",
    completed: "已完成",
    failed: "失败",
    timeout: "已超时",
  }
  return texts[status] || status
}

// 格式化时间
const formatTime = (time: string) => {
  return dayjs(time).format("MM-DD HH:mm")
}

// 页面加载
onMounted(() => {
  fetchHistory()

  // 检查是否有处理中的任务，有则开启轮询
  const hasProcessing = historyList.value.some(
    (t) => t.status === "pending" || t.status === "processing"
  )
  if (hasProcessing) {
    startPolling()
  }
})

// 页面卸载
onUnmounted(() => {
  stopPolling()
})
</script>

<style scoped lang="scss">
.ai-3d-container {
  display: flex;
  height: calc(100vh - 120px);
  min-height: 600px;
  background: #f5f5f5;
}

// 左侧面板
.left-panel {
  width: 320px;
  background: #1a1a2e;
  color: #fff;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}

.panel-header {
  padding: 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);

  :deep(.ant-segmented) {
    background: rgba(255, 255, 255, 0.1);

    .ant-segmented-item {
      color: rgba(255, 255, 255, 0.7);

      &-selected {
        background: #1890ff;
        color: #fff;
      }
    }
  }
}

.panel-content {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
}

.input-hint {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: 12px;
  line-height: 1.6;
}

.text-input {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #fff;
  resize: none;

  &::placeholder {
    color: rgba(255, 255, 255, 0.4);
  }

  &:focus {
    border-color: #1890ff;
  }

  :deep(.ant-input-data-count) {
    color: rgba(255, 255, 255, 0.5);
  }
}

.sample-prompts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
  align-items: center;

  .refresh-icon {
    color: rgba(255, 255, 255, 0.5);
    cursor: pointer;
    transition: color 0.3s;

    &:hover {
      color: #1890ff;
    }
  }

  .sample-tag {
    padding: 4px 12px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 16px;
    font-size: 12px;
    color: rgba(255, 255, 255, 0.7);
    cursor: pointer;
    transition: all 0.3s;

    &:hover {
      background: rgba(24, 144, 255, 0.3);
      color: #fff;
    }
  }
}

.image-upload {
  :deep(.ant-upload-drag) {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.2);

    &:hover {
      border-color: #1890ff;
    }

    .ant-upload-drag-icon {
      color: rgba(255, 255, 255, 0.5);
      font-size: 48px;
    }

    .ant-upload-text {
      color: rgba(255, 255, 255, 0.8);
    }

    .ant-upload-hint {
      color: rgba(255, 255, 255, 0.5);
    }
  }
}

.panel-footer {
  padding: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

// 右侧面板
.right-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

// 介绍区
.intro-section {
  padding: 40px;
  background: #fff;
  border-bottom: 1px solid #e8e8e8;
}

.intro-title {
  font-size: 28px;
  font-weight: 600;
  color: #1a1a2e;
  margin-bottom: 24px;
}

.intro-features {
  margin-bottom: 24px;
}

.feature-item {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
  font-size: 14px;
  color: #666;

  .feature-icon {
    margin-right: 12px;
    font-size: 16px;
  }
}

.intro-action {
  display: inline-block;
  color: #1890ff;
  font-size: 16px;
  cursor: pointer;
  margin-bottom: 8px;

  &:hover {
    text-decoration: underline;
  }
}

.intro-subtitle {
  color: #999;
  font-size: 13px;
  margin: 0;
}

// 历史记录区
.history-section {
  flex: 1;
  padding: 24px 40px;
  overflow-y: auto;
  background: #fafafa;
}

.history-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.history-title {
  font-size: 18px;
  font-weight: 500;
  color: #1a1a2e;
  margin: 0;
}

.view-all {
  color: #1890ff;
  cursor: pointer;

  &:hover {
    text-decoration: underline;
  }
}

.history-loading,
.history-empty {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 200px;
}

.history-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

.history-card {
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);

  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    transform: translateY(-2px);
  }
}

.card-preview {
  height: 140px;
  background: #1a1a2e;
  display: flex;
  align-items: center;
  justify-content: center;

  .preview-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .preview-loading,
  .preview-failed,
  .preview-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    color: rgba(255, 255, 255, 0.6);
    font-size: 24px;

    span {
      font-size: 12px;
    }
  }

  .preview-failed {
    color: #ff4d4f;
  }
}

.card-info {
  padding: 12px;
}

.card-desc {
  font-size: 13px;
  color: #333;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 8px;
}

.card-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-time {
  font-size: 12px;
  color: #999;
}

.card-actions {
  display: flex;
  gap: 8px;

  .action-icon {
    color: #666;
    cursor: pointer;
    transition: color 0.3s;

    &:hover {
      color: #1890ff;
    }

    &.danger:hover {
      color: #ff4d4f;
    }

    &.disabled {
      color: #ccc;
      cursor: not-allowed;
    }
  }
}

// 抽屉列表样式
.list-preview {
  width: 60px;
  height: 60px;
  background: #1a1a2e;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .list-preview-placeholder {
    color: rgba(255, 255, 255, 0.5);
    font-size: 20px;
  }
}

.list-desc {
  max-width: 300px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.list-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 12px;
  color: #999;
}

.danger-link {
  color: #ff4d4f;

  &:hover {
    color: #ff7875;
  }
}
</style>
