<template>
  <a-drawer
    v-model:open="visible"
    title="上传作品"
    placement="right"
    width="850px"
    :footer-style="{ textAlign: 'right', padding: '16px 24px' }"
    @close="handleCancel"
  >
    <template #title>
      <div class="drawer-title">
        <span>上传作品</span>
      </div>
    </template>

    <a-form
      ref="formRef"
      :model="form"
      :rules="rules"
      :label-col="{ span: 4 }"
      :wrapper-col="{ span: 20 }"
      layout="horizontal"
    >
      <a-form-item label="作品名称" name="title" required>
        <a-input
          v-model:value="form.title"
          placeholder="请输入作品名称"
          :maxlength="200"
        />
      </a-form-item>

      <a-form-item label="作品介绍" name="description" required>
        <a-textarea
          v-model:value="form.description"
          placeholder="请输入作品介绍"
          :rows="4"
          :maxlength="2000"
          show-count
        />
      </a-form-item>

      <a-form-item label="选择方式" required>
        <a-radio-group v-model:value="uploadMode" @change="handleModeChange">
          <a-radio value="history">从创作历史选择</a-radio>
          <a-radio value="local">本地上传</a-radio>
        </a-radio-group>
      </a-form-item>

      <!-- 从创作历史选择模式 -->
      <template v-if="uploadMode === 'history'">
        <a-form-item label="选择作品" name="selectedWork" required>
          <div class="work-selection">
            <!-- 加载状态 -->
            <div v-if="worksLoading" class="works-loading">
              <a-spin />
              <span>加载创作历史...</span>
            </div>

            <!-- 空状态 -->
            <div v-else-if="completedWorks.length === 0" class="works-empty">
              <a-empty description="暂无已完成的3D作品">
                <template #image>
                  <FileImageOutlined style="font-size: 48px; color: #d9d9d9" />
                </template>
              </a-empty>
              <a-button type="link" @click="goTo3DLab">
                前往3D建模实验室创作
              </a-button>
            </div>

            <!-- 作品网格 -->
            <div v-else class="works-grid">
              <div
                v-for="work in completedWorks"
                :key="work.id"
                class="work-card"
                :class="{ 'is-selected': form.selectedWorkId === work.id }"
                @click="handleSelectWork(work)"
              >
                <div class="work-preview">
                  <img
                    v-if="work.previewUrl"
                    :src="getPreviewUrl(work.previewUrl)"
                    alt="预览"
                    @error="handleImageError"
                  />
                  <div v-else class="preview-placeholder">
                    <FileImageOutlined />
                  </div>
                  <div v-if="form.selectedWorkId === work.id" class="selected-badge">
                    <CheckOutlined />
                  </div>
                </div>
                <div class="work-info">
                  <div class="work-desc" :title="work.inputContent">
                    {{ work.inputContent }}
                  </div>
                  <div class="work-time">
                    {{ formatTime(work.createTime) }}
                  </div>
                </div>
              </div>
            </div>

            <!-- 分页 -->
            <div v-if="worksPagination.total > worksPagination.pageSize" class="works-pagination">
              <a-pagination
                v-model:current="worksPagination.current"
                :total="worksPagination.total"
                :page-size="worksPagination.pageSize"
                size="small"
                @change="handleWorksPageChange"
              />
            </div>
          </div>
        </a-form-item>
      </template>

      <!-- 本地上传模式 -->
      <template v-else>
        <a-form-item label="上传作品" name="localWorkFile" required>
          <a-upload
            v-model:file-list="localWorkFileList"
            :before-upload="handleBeforeUploadWork"
            :remove="handleRemoveWork"
            :accept="workAcceptTypes"
            :max-count="1"
          >
            <a-button>
              <template #icon><UploadOutlined /></template>
              选择3D文件
            </a-button>
          </a-upload>
          <div class="upload-tip">
            支持格式：.obj, .fbx, .3ds, .dae, .blend, .stl, .ply, .gltf, .glb，最大500MB
          </div>
        </a-form-item>

        <a-form-item label="预览图" name="localPreviewFile" required>
          <a-upload
            v-model:file-list="localPreviewFileList"
            :before-upload="handleBeforeUploadPreview"
            :remove="handleRemovePreview"
            accept="image/*"
            :max-count="1"
            list-type="picture-card"
          >
            <div v-if="localPreviewFileList.length === 0" class="upload-placeholder">
              <PlusOutlined />
              <div>上传预览图</div>
            </div>
          </a-upload>
          <div class="upload-tip">
            请上传作品预览图，支持 JPG、PNG 格式，用于作品展示
          </div>
        </a-form-item>
      </template>

      <a-form-item label="上传附件">
        <a-upload
          v-model:file-list="attachmentFileList"
          :before-upload="handleBeforeUploadAttachment"
          :remove="handleRemoveAttachment"
          :max-count="5"
        >
          <a-button>
            <template #icon><UploadOutlined /></template>
            上传附件
          </a-button>
          <template #itemRender="{ file, actions }">
            <div class="attachment-item">
              <PaperClipOutlined />
              <span class="file-name">{{ file.name }}</span>
              <DeleteOutlined class="delete-icon" @click="actions.remove" />
            </div>
          </template>
        </a-upload>
        <div class="upload-tip">可上传补充材料，最多5个文件，单个文件不超过100MB</div>
      </a-form-item>
    </a-form>

    <template #footer>
      <a-space>
        <a-button @click="handleCancel">取消</a-button>
        <a-button type="primary" :loading="submitLoading" @click="handleSubmit">
          提交作品
        </a-button>
      </a-space>
    </template>
  </a-drawer>
</template>

<script setup lang="ts">
import { ref, reactive, watch, computed } from "vue"
import { useRouter, useRoute } from "vue-router"
import { message } from "ant-design-vue"
import {
  UploadOutlined,
  FileImageOutlined,
  CheckOutlined,
  PaperClipOutlined,
  DeleteOutlined,
  PlusOutlined,
} from "@ant-design/icons-vue"
import type { FormInstance, UploadFile } from "ant-design-vue"
import { worksApi, registrationsApi, type SubmitWorkForm } from "@/api/contests"
import { getAI3DTasks, type AI3DTask } from "@/api/ai-3d"
import { useAuthStore } from "@/stores/auth"
import request from "@/utils/request"
import dayjs from "dayjs"

interface Props {
  open: boolean
  contestId: number
}

interface Emits {
  (e: "update:open", value: boolean): void
  (e: "success"): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const router = useRouter()
const route = useRoute()
const authStore = useAuthStore()
const visible = ref(false)
const submitLoading = ref(false)
const formRef = ref<FormInstance>()

// 上传模式
const uploadMode = ref<"history" | "local">("history")

// 3D文件格式
const workAcceptTypes =
  ".obj,.fbx,.3ds,.dae,.blend,.max,.c4d,.stl,.ply,.gltf,.glb"

// 表单数据
const form = reactive<{
  title: string
  description: string
  // 历史记录模式
  selectedWorkId: number | null
  selectedWork: AI3DTask | null
  // 本地上传模式
  localWorkFile: File | null
  localPreviewFile: File | null
  // 附件
  attachmentFiles: File[]
}>({
  title: "",
  description: "",
  selectedWorkId: null,
  selectedWork: null,
  localWorkFile: null,
  localPreviewFile: null,
  attachmentFiles: [],
})

// 文件列表
const localWorkFileList = ref<UploadFile[]>([])
const localPreviewFileList = ref<UploadFile[]>([])
const attachmentFileList = ref<UploadFile[]>([])

// 3D作品列表
const worksLoading = ref(false)
const worksList = ref<AI3DTask[]>([])
const worksPagination = reactive({
  current: 1,
  pageSize: 8,
  total: 0,
})

// 只显示已完成的作品
const completedWorks = computed(() => {
  return worksList.value.filter((work) => work.status === "completed")
})

// 表单验证规则
const rules = computed(() => ({
  title: [{ required: true, message: "请输入作品名称", trigger: "blur" }],
  description: [{ required: true, message: "请输入作品介绍", trigger: "blur" }],
  selectedWork: [
    {
      required: uploadMode.value === "history",
      validator: () => {
        if (uploadMode.value === "history" && !form.selectedWorkId) {
          return Promise.reject(new Error("请选择一个3D作品"))
        }
        return Promise.resolve()
      },
      trigger: "change",
    },
  ],
  localWorkFile: [
    {
      required: uploadMode.value === "local",
      validator: () => {
        if (uploadMode.value === "local" && !form.localWorkFile) {
          return Promise.reject(new Error("请上传3D文件"))
        }
        return Promise.resolve()
      },
      trigger: "change",
    },
  ],
  localPreviewFile: [
    {
      required: uploadMode.value === "local",
      validator: () => {
        if (uploadMode.value === "local" && !form.localPreviewFile) {
          return Promise.reject(new Error("请上传预览图"))
        }
        return Promise.resolve()
      },
      trigger: "change",
    },
  ],
}))

watch(
  () => props.open,
  (newVal) => {
    visible.value = newVal
    if (newVal) {
      resetForm()
      fetchRegistrationId()
      fetchWorks()
    }
  },
  { immediate: true }
)

watch(visible, (newVal) => {
  emit("update:open", newVal)
})

// 模式切换时清空对应的数据
const handleModeChange = () => {
  if (uploadMode.value === "history") {
    form.localWorkFile = null
    form.localPreviewFile = null
    localWorkFileList.value = []
    localPreviewFileList.value = []
  } else {
    form.selectedWorkId = null
    form.selectedWork = null
  }
  formRef.value?.clearValidate()
}

// 获取报名记录ID
const registrationIdRef = ref<number | null>(null)

const fetchRegistrationId = async () => {
  if (!authStore.user?.id) {
    message.error("用户未登录")
    return
  }

  try {
    // 获取用户的报名记录（包括作为团队成员的情况）
    const registration = await registrationsApi.getMyRegistration(props.contestId)

    if (registration) {
      registrationIdRef.value = registration.id
    } else {
      message.warning("您尚未报名该活动或报名未通过，无法上传作品")
      visible.value = false
    }
  } catch (error: any) {
    message.error(error?.response?.data?.message || "获取报名信息失败")
    visible.value = false
  }
}

// 获取3D创作历史
const fetchWorks = async () => {
  worksLoading.value = true
  try {
    const res = await getAI3DTasks({
      page: worksPagination.current,
      pageSize: worksPagination.pageSize,
      status: "completed",
    })
    const data = res.data || res
    worksList.value = data.list || []
    worksPagination.total = data.total || 0
  } catch (error) {
    console.error("获取创作历史失败:", error)
    message.error("获取创作历史失败")
  } finally {
    worksLoading.value = false
  }
}

// 分页变化
const handleWorksPageChange = (page: number) => {
  worksPagination.current = page
  fetchWorks()
}

// 选择作品
const handleSelectWork = (work: AI3DTask) => {
  if (form.selectedWorkId === work.id) {
    form.selectedWorkId = null
    form.selectedWork = null
  } else {
    form.selectedWorkId = work.id
    form.selectedWork = work
    if (!form.title && work.inputContent) {
      form.title = work.inputContent.substring(0, 50)
    }
  }
}

// 获取预览图URL
const getPreviewUrl = (url: string) => {
  if (!url) return ""
  if (url.includes("tencentcos.cn") || url.includes("qcloud.com")) {
    return `/api/ai-3d/proxy-preview?url=${encodeURIComponent(url)}`
  }
  return url
}

// 图片加载错误处理
const handleImageError = (e: Event) => {
  const img = e.target as HTMLImageElement
  img.style.display = "none"
}

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

// 跳转到3D实验室
const goTo3DLab = () => {
  const tenantCode = route.params.tenantCode as string
  router.push(`/${tenantCode}/workbench/3d-lab`)
  visible.value = false
}

// 上传3D文件前验证
const handleBeforeUploadWork = (file: File): boolean => {
  const fileName = file.name.toLowerCase()
  const validExtensions = [
    ".obj", ".fbx", ".3ds", ".dae", ".blend",
    ".max", ".c4d", ".stl", ".ply", ".gltf", ".glb",
  ]

  const isValid = validExtensions.some((ext) => fileName.endsWith(ext))
  if (!isValid) {
    message.error("请上传支持的3D文件格式")
    return false
  }

  const maxSize = 500 * 1024 * 1024
  if (file.size > maxSize) {
    message.error("文件大小不能超过500MB")
    return false
  }

  form.localWorkFile = file
  return false
}

// 移除3D文件
const handleRemoveWork = () => {
  form.localWorkFile = null
  return true
}

// 上传预览图前验证
const handleBeforeUploadPreview = (file: File): boolean => {
  const isImage = file.type.startsWith("image/")
  if (!isImage) {
    message.error("请上传图片文件")
    return false
  }

  const maxSize = 10 * 1024 * 1024
  if (file.size > maxSize) {
    message.error("图片大小不能超过10MB")
    return false
  }

  form.localPreviewFile = file
  return false
}

// 移除预览图
const handleRemovePreview = () => {
  form.localPreviewFile = null
  return true
}

// 上传附件前验证
const handleBeforeUploadAttachment = (file: File): boolean => {
  const maxSize = 100 * 1024 * 1024
  if (file.size > maxSize) {
    message.error("附件大小不能超过100MB")
    return false
  }

  form.attachmentFiles.push(file)
  return false
}

// 移除附件
const handleRemoveAttachment = (file: UploadFile) => {
  const index = form.attachmentFiles.findIndex(
    (f) => f.name === file.name && f.size === file.size
  )
  if (index > -1) {
    form.attachmentFiles.splice(index, 1)
  }
  return true
}

// 重置表单
const resetForm = () => {
  uploadMode.value = "history"
  form.title = ""
  form.description = ""
  form.selectedWorkId = null
  form.selectedWork = null
  form.localWorkFile = null
  form.localPreviewFile = null
  form.attachmentFiles = []
  localWorkFileList.value = []
  localPreviewFileList.value = []
  attachmentFileList.value = []
  worksPagination.current = 1
  formRef.value?.resetFields()
}

// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return

  try {
    await formRef.value.validate()

    if (!registrationIdRef.value) {
      message.error("无法获取报名记录，请重新打开")
      return
    }

    submitLoading.value = true

    let modelFiles: string[] = []
    let previewUrl = ""
    let previewUrlsList: string[] = []

    if (uploadMode.value === "history") {
      // 从创作历史选择模式
      if (!form.selectedWork) {
        message.error("请选择一个3D作品")
        return
      }
      // 优先使用数组形式的 resultUrls 和 previewUrls
      const resultUrls = form.selectedWork.resultUrls || []
      previewUrlsList = form.selectedWork.previewUrls || []

      // 如果有多个模型URL，全部放入 files 数组
      if (resultUrls.length > 0) {
        modelFiles = [...resultUrls]
      } else if (form.selectedWork.resultUrl) {
        // 兼容旧数据，只有单个 resultUrl
        modelFiles = [form.selectedWork.resultUrl]
      }

      // 预览图：优先使用数组的第一个作为主预览图
      if (previewUrlsList.length > 0) {
        previewUrl = previewUrlsList[0]
      } else {
        previewUrl = form.selectedWork.previewUrl || ""
      }
    } else {
      // 本地上传模式
      if (!form.localWorkFile) {
        message.error("请上传3D文件")
        return
      }
      if (!form.localPreviewFile) {
        message.error("请上传预览图")
        return
      }

      // 上传3D文件
      try {
        const uploadedUrl = await uploadFile(form.localWorkFile)
        modelFiles = [uploadedUrl]
      } catch (error: any) {
        message.error("3D文件上传失败：" + (error?.message || "未知错误"))
        submitLoading.value = false
        return
      }

      // 上传预览图
      try {
        previewUrl = await uploadFile(form.localPreviewFile)
        previewUrlsList = [previewUrl]
      } catch (error: any) {
        message.error("预览图上传失败：" + (error?.message || "未知错误"))
        submitLoading.value = false
        return
      }
    }

    // 上传附件并收集附件信息
    const attachments: Array<{
      fileName: string
      fileUrl: string
      fileType?: string
      size?: string
    }> = []
    for (const file of form.attachmentFiles) {
      try {
        const url = await uploadFile(file)
        attachments.push({
          fileName: file.name,
          fileUrl: url,
          fileType: file.type || undefined,
          size: String(file.size),
        })
      } catch (error: any) {
        console.error("附件上传失败:", error)
      }
    }

    const submitData: SubmitWorkForm = {
      registrationId: registrationIdRef.value,
      title: form.title,
      description: form.description,
      files: modelFiles, // 只包含模型文件，不包含附件
      previewUrl: previewUrl,
      previewUrls: previewUrlsList.length > 0 ? previewUrlsList : undefined,
      attachments: attachments.length > 0 ? attachments : undefined,
    }

    await worksApi.submit(submitData)

    message.success("作品提交成功")
    emit("success")
    visible.value = false
    resetForm()
  } catch (error: any) {
    if (error?.errorFields) {
      return
    }
    message.error(error?.response?.data?.message || "作品提交失败")
  } finally {
    submitLoading.value = false
  }
}

// 文件上传函数
const uploadFile = async (file: File): Promise<string> => {
  const formData = new FormData()
  formData.append("file", file)

  try {
    const response = await request.post<any>("/upload", formData, {
      headers: {
        "Content-Type": "multipart/form-data",
      },
    })

    if (response && typeof response === "object" && "url" in response) {
      return String(response.url)
    }

    throw new Error("文件上传返回格式不正确")
  } catch (error: any) {
    console.error("文件上传失败:", error)
    throw new Error(error?.response?.data?.message || "文件上传失败")
  }
}

// 取消
const handleCancel = () => {
  visible.value = false
  resetForm()
}
</script>

<style lang="scss" scoped>
.drawer-title {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
}

.work-selection {
  border: 1px solid #d9d9d9;
  border-radius: 8px;
  padding: 16px;
  background: #fafafa;
  min-height: 200px;
}

.works-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 180px;
  color: #8c8c8c;
}

.works-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 180px;
}

.works-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

.work-card {
  background: #fff;
  border: 2px solid #e8e8e8;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.3s;

  &:hover {
    border-color: #1677ff;
    box-shadow: 0 2px 8px rgba(22, 119, 255, 0.15);
  }

  &.is-selected {
    border-color: #1677ff;
    box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.2);

    .work-preview {
      &::after {
        content: "";
        position: absolute;
        inset: 0;
        background: rgba(22, 119, 255, 0.1);
      }
    }
  }

  .work-preview {
    position: relative;
    height: 100px;
    background: #f0f0f0;
    display: flex;
    align-items: center;
    justify-content: center;

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

    .preview-placeholder {
      font-size: 32px;
      color: #d9d9d9;
    }

    .selected-badge {
      position: absolute;
      top: 8px;
      right: 8px;
      width: 24px;
      height: 24px;
      background: #1677ff;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
      font-size: 14px;
      z-index: 1;
    }
  }

  .work-info {
    padding: 8px;

    .work-desc {
      font-size: 12px;
      color: #303133;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      margin-bottom: 4px;
    }

    .work-time {
      font-size: 11px;
      color: #8c8c8c;
    }
  }
}

.works-pagination {
  margin-top: 16px;
  display: flex;
  justify-content: center;
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #8c8c8c;

  .anticon {
    font-size: 24px;
    margin-bottom: 8px;
  }
}

.attachment-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  background: #f5f5f5;
  border-radius: 4px;
  margin-top: 8px;

  .file-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
  }

  .delete-icon {
    color: #8c8c8c;
    cursor: pointer;
    transition: color 0.3s;

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

.upload-tip {
  margin-top: 8px;
  font-size: 12px;
  color: #8c8c8c;
}

:deep(.ant-upload-list) {
  &.ant-upload-list-picture-card {
    display: flex;
  }
}

:deep(.ant-upload-select-picture-card) {
  width: 120px !important;
  height: 120px !important;
}

:deep(.ant-upload-list-item-container) {
  width: 120px !important;
  height: 120px !important;
}
</style>
