<template>
  <a-drawer
    :open="open"
    :title="drawerTitle"
    placement="right"
    :width="1100"
    :closable="true"
    :destroy-on-close="true"
    @close="handleClose"
  >
    <a-spin :spinning="loading">
      <div class="review-drawer-content">
        <!-- 左侧：作品信息 -->
        <div class="left-panel">
          <!-- 提交时间 -->
          <div class="submit-time">
            {{ formatDate(workDetail?.submitTime) }}
          </div>

          <!-- 作品名称 -->
          <div class="section">
            <div class="section-label">作品名称</div>
            <div class="section-content">{{ workDetail?.title || '-' }}</div>
          </div>

          <!-- 作品介绍 -->
          <div class="section">
            <div class="section-label">作品介绍</div>
            <div class="section-content description">
              {{ workDetail?.description || '-' }}
            </div>
          </div>

          <!-- 作品详情 -->
          <div class="section">
            <div class="section-label">作品详情</div>
            <div class="work-tabs" v-if="modelItems.length > 1">
              <a-button
                v-for="(item, index) in modelItems"
                :key="index"
                :type="currentFileIndex === index ? 'primary' : 'default'"
                size="small"
                @click="currentFileIndex = index"
              >
                作品{{ index + 1 }}
              </a-button>
            </div>
            <!-- 预览区域 -->
            <div
              class="preview-area"
              @mouseenter="isHovering = true"
              @mouseleave="isHovering = false"
            >
              <img
                v-if="currentPreviewImage"
                :src="currentPreviewImage"
                alt="作品预览"
                class="preview-image"
              />
              <div v-else class="preview-placeholder">
                <FileImageOutlined />
                <span>暂无预览</span>
              </div>
              <!-- 悬浮预览按钮 -->
              <transition name="fade">
                <div v-show="isHovering && currentModelUrl" class="preview-overlay">
                  <a-button type="primary" @click="handlePreview3DModel">
                    <template #icon><EyeOutlined /></template>
                    3D预览
                  </a-button>
                </div>
              </transition>
            </div>
          </div>

          <!-- 作品附件 -->
          <div class="section" v-if="workDetail?.attachments?.length">
            <div class="section-label">作品附件</div>
            <div class="attachments-list">
              <div
                v-for="attachment in workDetail.attachments"
                :key="attachment.id"
                class="attachment-group"
              >
                <div class="attachment-name">附件名称：{{ getAttachmentCategory(attachment) }}</div>
                <div class="attachment-item">
                  <PaperClipOutlined class="attachment-icon" />
                  <span class="file-name">{{ attachment.fileName }}</span>
                  <a-button
                    type="link"
                    size="small"
                    @click="downloadAttachment(attachment)"
                  >
                    <DownloadOutlined />
                  </a-button>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- 右侧：评分区域 -->
        <div class="right-panel">
          <div class="scoring-section">
            <div class="scoring-title">作品打分</div>

            <!-- 评分标准说明（有评审规则时显示） -->
            <div class="scoring-standard" v-if="reviewRule">
              <div class="standard-title">评分标准</div>
              <div class="standard-content">
                <div
                  v-for="(dim, index) in reviewRule.dimensions"
                  :key="index"
                  class="dimension-desc"
                >
                  <span class="dim-name">{{ dim.name }}（{{ dim.percentage }}分）：</span>
                  <span class="dim-desc">{{ dim.description || '无说明' }}</span>
                </div>
              </div>
            </div>

            <!-- 已评审：显示保存的维度评分数据 -->
            <template v-if="isReviewed && savedDimensionScores.length > 0">
              <div class="dimension-scores">
                <div
                  v-for="(dim, index) in savedDimensionScores"
                  :key="index"
                  class="dimension-item"
                >
                  <div class="dimension-label">{{ dim.name }}（满分{{ dim.maxScore }}分）</div>
                  <div class="dimension-input">
                    <a-input-number
                      :value="dim.score"
                      :disabled="true"
                      size="small"
                      class="score-input"
                    />
                    <span class="score-unit">分</span>
                  </div>
                </div>
              </div>
            </template>

            <!-- 未评审：显示当前评审规则的维度评分输入 -->
            <template v-else-if="reviewRule && !isReviewed">
              <!-- 各维度评分 -->
              <div class="dimension-scores">
                <div
                  v-for="(dim, index) in reviewRule.dimensions"
                  :key="index"
                  class="dimension-item"
                >
                  <div class="dimension-label">{{ dim.name }}（满分{{ dim.percentage }}分）</div>
                  <div class="dimension-input">
                    <a-button
                      size="small"
                      @click="decreaseScore(index)"
                    >-</a-button>
                    <a-input-number
                      v-model:value="dimensionScores[index]"
                      :min="0"
                      :max="dim.percentage"
                      :precision="0"
                      size="small"
                      class="score-input"
                    />
                    <span class="score-unit">分</span>
                    <a-button
                      size="small"
                      @click="increaseScore(index, dim.percentage)"
                    >+</a-button>
                  </div>
                </div>
              </div>
            </template>

            <!-- 简单评分模式（无评审规则时） -->
            <div class="simple-score" v-else>
              <div class="dimension-label">评分（满分100分）</div>
              <div class="dimension-input">
                <a-input-number
                  v-model:value="simpleScore"
                  :min="0"
                  :max="100"
                  :precision="2"
                  :disabled="isReviewed"
                  style="width: 150px"
                />
                <span class="score-unit">分</span>
              </div>
            </div>

            <!-- 总得分 -->
            <div class="total-score">
              <span class="total-label">总得分</span>
              <span class="total-value">{{ totalScore }}</span>
              <span class="total-unit">分</span>
            </div>

            <!-- 老师点评 -->
            <div class="comments-section">
              <div class="comments-title">老师点评</div>
              <a-select
                v-model:value="selectedPresetComment"
                placeholder="选择预设点评"
                style="width: 100%; margin-bottom: 12px"
                :disabled="isReviewed"
                allow-clear
                @change="handlePresetSelect"
              >
                <a-select-option
                  v-for="preset in presetComments"
                  :key="preset.id"
                  :value="preset.id"
                >
                  {{ preset.content }}
                </a-select-option>
              </a-select>
              <a-textarea
                v-model:value="comments"
                placeholder="请输入评语或选择预设评语"
                :rows="4"
                :maxlength="500"
                show-count
                :disabled="isReviewed"
              />
            </div>

            <!-- 操作按钮 -->
            <div class="action-buttons" v-if="!isReviewed">
              <a-button type="primary" :loading="submitLoading" @click="handleSubmit">
                提交
              </a-button>
              <a-button @click="handleReset">重置</a-button>
              <a-button danger @click="handleViolation">违规</a-button>
            </div>
          </div>
        </div>
      </div>
    </a-spin>
  </a-drawer>
</template>

<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { message, Modal } from "ant-design-vue";
import {
  PaperClipOutlined,
  DownloadOutlined,
  FileImageOutlined,
  EyeOutlined,
} from "@ant-design/icons-vue";
import dayjs from "dayjs";
import { worksApi, reviewsApi, contestsApi } from "@/api/contests";
import { presetCommentsApi } from "@/api/preset-comments";
import type { ContestReviewRule, ReviewDimension } from "@/api/contests";
import type { PresetComment } from "@/api/preset-comments";

const props = defineProps<{
  open: boolean;
  assignmentId: number | null;
  workId: number | null;
  contestId: number | null;
  workList?: Array<{ workId: number; assignmentId: number }>;
  currentIndex?: number;
}>();

const emit = defineEmits<{
  (e: "update:open", value: boolean): void;
  (e: "success"): void;
  (e: "navigate", index: number): void;
}>();

const route = useRoute();
const router = useRouter();
const tenantCode = route.params.tenantCode as string;

// 加载状态
const loading = ref(false);
const submitLoading = ref(false);

// 作品详情
const workDetail = ref<any>(null);

// 评审规则
const reviewRule = ref<ContestReviewRule | null>(null);

// 预设评语
const presetComments = ref<PresetComment[]>([]);
const selectedPresetComment = ref<number | undefined>(undefined);

// 评分数据
const existingScore = ref<any>(null);
const dimensionScores = ref<number[]>([]);
const simpleScore = ref<number | undefined>(undefined);
const comments = ref("");

// 保存的维度评分数据（用于已评审时的回显）
const savedDimensionScores = ref<Array<{ name: string; score: number; maxScore: number }>>([]);

// 当前选中的文件索引
const currentFileIndex = ref(0);

// 鼠标悬浮状态
const isHovering = ref(false);

// 是否已评审
const isReviewed = computed(() => existingScore.value !== null);

// 抽屉标题
const drawerTitle = computed(() => {
  const contestName = workDetail.value?.contest?.contestName || "活动";
  return `${contestName}作品评审`;
});

// 模型项目列表 - 解析 files 和 previewUrls 数组
interface ModelItem {
  fileUrl: string;
  previewUrl: string;
}

const modelItems = computed<ModelItem[]>(() => {
  if (!workDetail.value) return [];

  // 解析 files 数组
  let files = workDetail.value.files || [];
  if (typeof files === "string") {
    try {
      files = JSON.parse(files);
    } catch {
      files = [];
    }
  }
  if (!Array.isArray(files)) files = [];

  // 解析 previewUrls 数组
  let previewUrls = workDetail.value.previewUrls || [];
  if (typeof previewUrls === "string") {
    try {
      previewUrls = JSON.parse(previewUrls);
    } catch {
      previewUrls = [];
    }
  }
  if (!Array.isArray(previewUrls)) previewUrls = [];

  // 如果没有 previewUrls 但有单个 previewUrl，使用它
  if (previewUrls.length === 0 && workDetail.value.previewUrl) {
    previewUrls = [workDetail.value.previewUrl];
  }

  // 过滤出3D模型文件
  const modelFiles = files.filter((f: any) => {
    const url = typeof f === "object" && f?.fileUrl ? f.fileUrl : f;
    return url && is3DModel(url);
  });

  // 构建模型项目列表
  if (modelFiles.length > 0) {
    return modelFiles.map((f: any, index: number) => {
      const fileUrl = typeof f === "object" && f?.fileUrl ? f.fileUrl : f;
      const previewUrl = previewUrls[index] || previewUrls[0] || "";
      return {
        fileUrl: getFileUrl(fileUrl),
        previewUrl: previewUrl ? getFileUrl(previewUrl) : "",
      };
    });
  }

  // 如果没有3D模型文件，但有预览图，也显示
  if (previewUrls.length > 0) {
    return previewUrls.map((url: string) => ({
      fileUrl: "",
      previewUrl: getFileUrl(url),
    }));
  }

  return [];
});

// 获取文件URL（处理相对路径）
const getFileUrl = (fileUrl: string): string => {
  if (!fileUrl) return "";
  if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
    return fileUrl;
  }
  const baseURL = import.meta.env.VITE_API_BASE_URL || "";
  if (fileUrl.startsWith("/api") && baseURL.includes("/api")) {
    const urlWithoutApi = baseURL.replace(/\/api$/, "");
    return `${urlWithoutApi}${fileUrl}`;
  }
  return `${baseURL}${fileUrl.startsWith("/") ? "" : "/"}${fileUrl}`;
};

// 当前3D模型URL
const currentModelUrl = computed(() => {
  const item = modelItems.value[currentFileIndex.value];
  return item?.fileUrl || null;
});

// 当前预览图
const currentPreviewImage = computed(() => {
  const item = modelItems.value[currentFileIndex.value];
  return item?.previewUrl || workDetail.value?.previewUrl || null;
});

// 总分计算
const totalScore = computed(() => {
  // 如果已评审，直接返回数据库存储的总分
  if (isReviewed.value && existingScore.value?.totalScore !== null) {
    return Number(existingScore.value.totalScore);
  }
  // 否则根据当前输入计算
  if (reviewRule.value) {
    return dimensionScores.value.reduce((sum, score) => sum + (score || 0), 0);
  }
  return simpleScore.value || 0;
});

// 判断是否是3D模型文件
const is3DModel = (fileName: string) => {
  if (!fileName) return false;
  const ext = fileName.toLowerCase();
  return ['.glb', '.gltf', '.obj', '.fbx', '.stl'].some(e => ext.endsWith(e));
};

// 格式化日期
const formatDate = (dateStr?: string) => {
  if (!dateStr) return "-";
  return dayjs(dateStr).format("YYYY.MM.DD  HH:mm");
};

// 获取附件分类名
const getAttachmentCategory = (attachment: any) => {
  const fileName = attachment.fileName || '';
  const ext = fileName.split('.').pop()?.toLowerCase() || '';
  if (['zip', 'rar', '7z'].includes(ext)) return fileName.replace(/\.[^.]+$/, '');
  return fileName;
};

// 下载附件
const downloadAttachment = (attachment: any) => {
  const link = document.createElement('a');
  link.href = attachment.fileUrl;
  link.download = attachment.fileName;
  link.target = '_blank';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};

// 增加分数
const increaseScore = (index: number, maxScore: number) => {
  const current = dimensionScores.value[index] || 0;
  if (current < maxScore) {
    dimensionScores.value[index] = current + 1;
  }
};

// 减少分数
const decreaseScore = (index: number) => {
  const current = dimensionScores.value[index] || 0;
  if (current > 0) {
    dimensionScores.value[index] = current - 1;
  }
};

// 选择预设评语
const handlePresetSelect = (presetId: number | undefined) => {
  if (presetId) {
    const preset = presetComments.value.find(p => p.id === presetId);
    if (preset) {
      comments.value = preset.content;
      // 增加使用次数
      presetCommentsApi.incrementUseCount(presetId).catch(() => {});
    }
  }
};

// 获取作品详情
const fetchWorkDetail = async () => {
  if (!props.workId) return;

  loading.value = true;
  try {
    const detail = await worksApi.getDetail(props.workId);
    workDetail.value = detail;

    // 获取活动的评审规则
    if (props.contestId) {
      try {
        const contest = await contestsApi.getDetail(props.contestId);

        if (contest.reviewRule) {
          // 确保 dimensions 是数组（可能是 JSON 字符串）
          let dims = contest.reviewRule.dimensions;
          if (typeof dims === 'string') {
            try {
              dims = JSON.parse(dims);
            } catch {
              dims = [];
            }
          }
          reviewRule.value = {
            ...contest.reviewRule,
            dimensions: Array.isArray(dims) ? dims : []
          };
        } else {
          reviewRule.value = null;
        }

        // 初始化维度分数
        if (reviewRule.value?.dimensions?.length) {
          dimensionScores.value = reviewRule.value.dimensions.map(() => 0);
        }
      } catch {
        // 获取评审规则失败，使用简单评分模式
        reviewRule.value = null;
      }

      // 单独获取预设评语，不影响评审规则
      try {
        const presets = await presetCommentsApi.getList(props.contestId);
        presetComments.value = presets;
      } catch {
        presetComments.value = [];
      }
    }

    // 获取当前评委的评分记录
    const scores = await reviewsApi.getWorkScores(props.workId);
    const myScore = scores.find((s: any) => s.assignmentId === props.assignmentId);
    if (myScore && myScore.totalScore !== null && myScore.totalScore !== undefined) {
      existingScore.value = myScore;
      if (myScore.dimensionScores) {
        // 解析保存的维度评分数据
        const dimScores = typeof myScore.dimensionScores === 'string'
          ? JSON.parse(myScore.dimensionScores)
          : myScore.dimensionScores;
        // 直接保存原始数据用于回显
        savedDimensionScores.value = Array.isArray(dimScores) ? dimScores : [];
        // 同时映射到 dimensionScores 数组（用于表单绑定）
        if (reviewRule.value?.dimensions) {
          dimensionScores.value = reviewRule.value.dimensions.map((dim: ReviewDimension) => {
            const found = dimScores.find((ds: any) => ds.name === dim.name);
            return found ? found.score : 0;
          });
        }
      } else {
        savedDimensionScores.value = [];
        simpleScore.value = Number(myScore.totalScore);
      }
      comments.value = myScore.comments || "";
    } else {
      existingScore.value = null;
      savedDimensionScores.value = [];
      resetForm();
    }

    currentFileIndex.value = 0;
  } catch (error: any) {
    message.error(error?.response?.data?.message || "获取作品详情失败");
  } finally {
    loading.value = false;
  }
};

// 重置表单
const resetForm = () => {
  if (reviewRule.value?.dimensions) {
    dimensionScores.value = reviewRule.value.dimensions.map(() => 0);
  }
  simpleScore.value = undefined;
  comments.value = "";
  selectedPresetComment.value = undefined;
  savedDimensionScores.value = [];
};

// 提交评分
const handleSubmit = async () => {
  if (!props.assignmentId || !props.workId) return;

  // 验证评分
  if (reviewRule.value) {
    const hasInvalidScore = dimensionScores.value.some((score, idx) => {
      const dim = reviewRule.value!.dimensions[idx];
      return score === undefined || score === null || score < 0 || score > dim.percentage;
    });
    if (hasInvalidScore) {
      message.warning("请为所有评分维度填写有效分数");
      return;
    }
  } else {
    if (simpleScore.value === undefined || simpleScore.value === null) {
      message.warning("请输入评分");
      return;
    }
  }

  submitLoading.value = true;
  try {
    const scoreData: any = {
      assignmentId: props.assignmentId,
      workId: props.workId,
      totalScore: totalScore.value,
      comments: comments.value || undefined,
    };

    // 如果有维度评分，添加维度数据
    if (reviewRule.value?.dimensions) {
      scoreData.dimensionScores = reviewRule.value.dimensions.map((dim, idx) => ({
        name: dim.name,
        score: dimensionScores.value[idx] || 0,
        maxScore: dim.percentage,
      }));
    }

    await reviewsApi.score(scoreData);
    message.success("评分提交成功");
    emit("success");
    handleClose();
  } catch (error: any) {
    message.error(error?.response?.data?.message || "提交失败");
  } finally {
    submitLoading.value = false;
  }
};

// 重置
const handleReset = () => {
  resetForm();
};

// 标记违规
const handleViolation = () => {
  Modal.confirm({
    title: "标记违规",
    content: "确定要将该作品标记为违规吗？标记后该作品将被记录为违规作品。",
    okText: "确定",
    cancelText: "取消",
    okButtonProps: { danger: true },
    onOk: async () => {
      // TODO: 实现违规标记功能
      message.info("违规标记功能开发中");
    },
  });
};

// 3D模型预览
const handlePreview3DModel = () => {
  const fileUrl = currentModelUrl.value;
  if (!fileUrl) {
    message.error("文件路径无效");
    return;
  }

  // 收集所有模型URL用于多模型切换
  const allModelUrls = modelItems.value
    .filter((m) => m.fileUrl)
    .map((m) => m.fileUrl);

  // 存储到 sessionStorage（避免URL过长）
  if (allModelUrls.length > 1) {
    sessionStorage.setItem("model-viewer-urls", JSON.stringify(allModelUrls));
    sessionStorage.setItem("model-viewer-index", String(currentFileIndex.value));
    sessionStorage.removeItem("model-viewer-url");
  } else {
    sessionStorage.setItem("model-viewer-url", fileUrl);
    sessionStorage.removeItem("model-viewer-urls");
    sessionStorage.removeItem("model-viewer-index");
  }

  router.push({
    path: `/${tenantCode}/workbench/model-viewer`,
  });
};

// 关闭抽屉
const handleClose = () => {
  emit("update:open", false);
};

// 监听抽屉打开
watch(
  () => props.open,
  (val) => {
    if (val && props.workId) {
      fetchWorkDetail();
    } else {
      workDetail.value = null;
      existingScore.value = null;
      reviewRule.value = null;
      presetComments.value = [];
      resetForm();
    }
  }
);

// 监听 workId 变化（切换作品时）
watch(
  () => props.workId,
  (val) => {
    if (props.open && val) {
      fetchWorkDetail();
    }
  }
);
</script>

<style scoped lang="scss">
$primary: #0958d9;

.review-drawer-content {
  display: flex;
  gap: 24px;
  min-height: calc(100vh - 110px);
}

.left-panel {
  flex: 1;
  min-width: 0;
}

.right-panel {
  width: 320px;
  flex-shrink: 0;
}

.submit-time {
  color: #666;
  font-size: 14px;
  margin-bottom: 16px;
}

.section {
  margin-bottom: 20px;

  .section-label {
    font-weight: 600;
    color: #333;
    margin-bottom: 8px;
    font-size: 14px;
  }

  .section-content {
    color: #333;
    line-height: 1.6;

    &.description {
      color: #666;
    }
  }
}

.work-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.preview-area {
  position: relative;
  width: 100%;
  height: 400px;
  background: #f5f5f5;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  cursor: pointer;

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

  .preview-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    color: #999;

    .anticon {
      font-size: 48px;
    }
  }

  .preview-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

// 淡入淡出动画
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.attachments-list {
  .attachment-group {
    margin-bottom: 12px;

    .attachment-name {
      font-size: 13px;
      color: #666;
      margin-bottom: 4px;
    }

    .attachment-item {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 8px 12px;
      background: #f0f7ff;
      border-radius: 6px;

      .attachment-icon {
        color: #52c41a;
        font-size: 16px;
      }

      .file-name {
        flex: 1;
        color: #333;
        font-size: 13px;
      }
    }
  }
}

.scoring-section {
  background: #fff;
  border-radius: 8px;

  .scoring-title {
    font-size: 16px;
    font-weight: 600;
    color: #333;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid #f0f0f0;
  }
}

.scoring-standard {
  margin-bottom: 20px;
  padding: 12px;
  background: #fafafa;
  border-radius: 6px;

  .standard-title {
    font-weight: 600;
    color: #333;
    margin-bottom: 8px;
    font-size: 13px;
  }

  .standard-content {
    font-size: 12px;
    color: #666;
    line-height: 1.8;

    .dimension-desc {
      margin-bottom: 4px;

      .dim-name {
        color: #333;
        font-weight: 500;
      }
    }
  }
}

.dimension-scores {
  margin-bottom: 20px;

  .dimension-item {
    margin-bottom: 16px;

    .dimension-label {
      font-size: 13px;
      color: #333;
      margin-bottom: 8px;
    }

    .dimension-input {
      display: flex;
      align-items: center;
      gap: 8px;

      .score-input {
        width: 60px;
        text-align: center;
      }

      .score-unit {
        color: #666;
        font-size: 13px;
      }
    }
  }
}

.simple-score {
  margin-bottom: 20px;

  .dimension-label {
    font-size: 13px;
    color: #333;
    margin-bottom: 8px;
  }

  .dimension-input {
    display: flex;
    align-items: center;
    gap: 8px;

    .score-unit {
      color: #666;
    }
  }
}

.total-score {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 24px;
  padding: 12px;
  background: #f6ffed;
  border-radius: 6px;

  .total-label {
    font-weight: 600;
    color: #333;
  }

  .total-value {
    font-size: 24px;
    font-weight: 700;
    color: $primary;
  }

  .total-unit {
    color: #666;
  }
}

.comments-section {
  margin-bottom: 24px;

  .comments-title {
    font-weight: 600;
    color: #333;
    margin-bottom: 12px;
    font-size: 14px;
  }
}

.action-buttons {
  display: flex;
  gap: 12px;

  .ant-btn {
    flex: 1;
  }
}
</style>
