<template>
  <div v-if="isShowModal" class="modal modal-open overflow-hidden">
    <div class="modal-box w-full max-w-7xl max-h-[90vh] p-0 overflow-hidden">
      <div
        class="flex justify-between items-center p-6 border-b border-base-300"
      >
        <h2 class="text-2xl font-bold text-base-content">
          {{ mode === "create" ? "新建实验" : "编辑实验" }}
        </h2>
        <button @click="close" class="btn btn-sm btn-circle btn-ghost">
          <XIcon class="w-6 h-6" />
        </button>
      </div>

      <form @submit.prevent="submitCreateExam" class="flex h-[calc(90vh-5rem)]">
        <!-- 左侧：基本信息 -->
        <div class="w-110 p-6 overflow-y-auto border-r border-base-300">
          <div class="space-y-6">
            <h3 class="text-xl font-semibold text-base-content mb-4">
              基本信息
            </h3>

            <!-- 实验ID -->
            <div class="form-control">
              <label class="label">
                <span class="label-text font-medium">实验ID *</span>
              </label>
              <input
                type="text"
                v-model="editExamInfo.id"
                class="input input-bordered w-full"
                placeholder="例如: EXP001"
                required
              />
            </div>

            <!-- 实验名称 -->
            <div class="form-control">
              <label class="label">
                <span class="label-text font-medium">实验名称 *</span>
              </label>
              <input
                type="text"
                v-model="editExamInfo.name"
                class="input input-bordered w-full"
                placeholder="实验名称"
                required
              />
            </div>

            <!-- 实验描述 -->
            <div class="form-control">
              <label class="label">
                <span class="label-text font-medium">实验描述 *</span>
              </label>
              <textarea
                v-model="editExamInfo.description"
                class="textarea textarea-bordered w-full h-32"
                placeholder="详细描述实验内容、目标和要求..."
                required
              ></textarea>
            </div>

            <!-- 标签 -->
            <div class="form-control">
              <div class="flex flex-wrap gap-2 mb-3 min-h-[2rem]">
                <span
                  v-for="(tag, index) in editExamInfo.tags"
                  :key="index"
                  class="badge badge-primary gap-2"
                >
                  {{ tag }}
                  <button
                    type="button"
                    @click="removeTag(index)"
                    class="text-primary-content hover:text-error"
                  >
                    <svg
                      class="w-3 h-3"
                      fill="none"
                      stroke="currentColor"
                      viewBox="0 0 24 24"
                    >
                      <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        stroke-width="2"
                        d="M6 18L18 6M6 6l12 12"
                      />
                    </svg>
                  </button>
                </span>
              </div>
              <div class="flex gap-2">
                <input
                  type="text"
                  v-model="newTagInput"
                  @keydown.enter.prevent="addTag"
                  class="input input-bordered flex-1"
                  placeholder="输入标签按回车添加"
                />
              </div>
            </div>

            <!-- 难度等级 -->
            <div class="form-control">
              <div class="flex items-center justify-between p-4 rounded-lg">
                <span class="label-text font-medium">难度等级 *</span>
                <div class="flex items-center gap-4">
                  <div class="rating rating-lg">
                    <input
                      v-for="i in 5"
                      :key="i"
                      type="radio"
                      :value="i"
                      v-model="editExamInfo.difficulty"
                      class="mask mask-star-2 bg-orange-400"
                    />
                  </div>
                  <span class="text-lg font-medium text-base-content"
                    >({{ editExamInfo.difficulty }}/5)</span
                  >
                </div>
              </div>
            </div>

            <!-- 可见性 -->
            <div class="form-control">
              <div class="p-4 rounded-lg">
                <label class="label cursor-pointer justify-start gap-4">
                  <input
                    type="checkbox"
                    v-model="editExamInfo.isVisibleToUsers"
                    class="checkbox checkbox-primary"
                  />
                  <div>
                    <span class="label-text font-medium">对学生可见</span>
                    <div class="text-sm text-base-content/70">
                      开启后学生可以在实验列表中看到此实验
                    </div>
                  </div>
                </label>
              </div>
            </div>

            <!-- 提交按钮 -->
            <div class="pt-4 border-t border-base-300">
              <div class="space-y-3">
                <button
                  type="submit"
                  :disabled="isUpdating || !canCreateExam"
                  class="btn btn-primary w-full"
                >
                  <span
                    v-if="isUpdating"
                    class="loading loading-spinner loading-sm mr-2"
                  ></span>
                  {{
                    mode === "create"
                      ? isUpdating
                        ? "创建中..."
                        : "创建实验"
                      : isUpdating
                        ? "更新中..."
                        : "更新实验"
                  }}
                </button>
              </div>
            </div>
          </div>
        </div>

        <!-- 右侧：文件上传 -->
        <div class="flex-1 p-6 overflow-y-auto">
          <div class="space-y-6">
            <h3 class="text-xl font-semibold text-base-content mb-4">
              资源文件
            </h3>

            <!-- 第一行：MD文档 和 图片资源 -->
            <div class="grid grid-cols-2 gap-4">
              <!-- MD文档 -->
              <div class="space-y-2">
                <label class="text-sm font-medium text-base-content"
                  >MD文档 (可选)</label
                >
                <div
                  class="border-2 border-dashed border-base-300 rounded-lg p-6 text-center cursor-pointer hover:border-primary hover:bg-primary/5 transition-colors aspect-square flex items-center justify-center"
                  @click="mdFileInput?.click()"
                  @dragover.prevent
                  @dragenter.prevent
                  @drop.prevent="(e) => handleFileDrop(e, 'md')"
                >
                  <div
                    v-if="!uploadFiles.mdFile"
                    class="flex flex-col items-center gap-3"
                  >
                    <FileTextIcon
                      class="w-12 h-12 text-base-content opacity-40"
                    />
                    <div class="text-sm text-base-content/70 text-center">
                      <div class="font-medium mb-1">点击或拖拽上传</div>
                      <div class="text-xs">支持 .md 文件</div>
                    </div>
                  </div>
                  <div v-else class="flex flex-col items-center gap-2">
                    <FileTextIcon class="w-8 h-8 text-success" />
                    <div class="text-xs font-medium text-success text-center">
                      {{ uploadFiles.mdFile.name }}
                    </div>
                    <div class="text-xs text-base-content/50">点击重新选择</div>
                  </div>
                </div>
                <input
                  type="file"
                  ref="mdFileInput"
                  @change="(e) => handleFileChange(e, 'md')"
                  accept=".md"
                  class="hidden"
                />
              </div>

              <!-- 图片资源 -->
              <div class="space-y-2">
                <label class="text-sm font-medium text-base-content"
                  >图片资源 (可选)</label
                >
                <div
                  class="border-2 border-dashed border-base-300 rounded-lg p-6 text-center cursor-pointer hover:border-primary hover:bg-primary/5 transition-colors aspect-square flex items-center justify-center"
                  @click="imageFilesInput?.click()"
                  @dragover.prevent
                  @dragenter.prevent
                  @drop.prevent="(e) => handleFileDrop(e, 'image')"
                >
                  <div
                    v-if="uploadFiles.imageFiles.length === 0"
                    class="flex flex-col items-center gap-3"
                  >
                    <ImageIcon class="w-12 h-12 text-base-content opacity-40" />
                    <div class="text-sm text-base-content/70 text-center">
                      <div class="font-medium mb-1">点击或拖拽上传</div>
                      <div class="text-xs">支持 PNG, JPG, GIF 等图片格式</div>
                    </div>
                  </div>
                  <div v-else class="flex flex-col items-center gap-2">
                    <ImageIcon class="w-8 h-8 text-success" />
                    <div class="text-xs font-medium text-success">
                      {{ uploadFiles.imageFiles.length }} 个文件
                    </div>
                    <div class="text-xs text-base-content/50">点击重新选择</div>
                  </div>
                </div>
                <input
                  type="file"
                  ref="imageFilesInput"
                  @change="(e) => handleFileChange(e, 'image')"
                  accept="image/*"
                  multiple
                  class="hidden"
                />
              </div>
            </div>

            <!-- 第二行：示例比特流 和 画布模板 -->
            <div class="grid grid-cols-2 gap-4">
              <!-- 示例比特流 -->
              <div class="space-y-2">
                <label class="text-sm font-medium text-base-content"
                  >示例比特流 (可选)</label
                >
                <div
                  class="border-2 border-dashed border-base-300 rounded-lg p-6 text-center cursor-pointer hover:border-primary hover:bg-primary/5 transition-colors aspect-square flex items-center justify-center"
                  @click="bitstreamFilesInput?.click()"
                  @dragover.prevent
                  @dragenter.prevent
                  @drop.prevent="(e) => handleFileDrop(e, 'bitstream')"
                >
                  <div
                    v-if="uploadFiles.bitstreamFiles.length === 0"
                    class="flex flex-col items-center gap-3"
                  >
                    <BinaryIcon
                      class="w-12 h-12 text-base-content opacity-40"
                    />
                    <div class="text-sm text-base-content/70 text-center">
                      <div class="font-medium mb-1">点击或拖拽上传</div>
                      <div class="text-xs">支持 .sbit, .bit, .bin 文件</div>
                    </div>
                  </div>
                  <div v-else class="flex flex-col items-center gap-2">
                    <BinaryIcon class="w-8 h-8 text-success" />
                    <div class="text-xs font-medium text-success">
                      {{ uploadFiles.bitstreamFiles.length }} 个文件
                    </div>
                    <div class="text-xs text-base-content/50">点击重新选择</div>
                  </div>
                </div>
                <input
                  type="file"
                  ref="bitstreamFilesInput"
                  @change="(e) => handleFileChange(e, 'bitstream')"
                  accept=".sbit,.bit,.bin"
                  multiple
                  class="hidden"
                />
              </div>

              <!-- 画布模板 -->
              <div class="space-y-2">
                <label class="text-sm font-medium text-base-content"
                  >画布模板 (可选)</label
                >
                <div
                  class="border-2 border-dashed border-base-300 rounded-lg p-6 text-center cursor-pointer hover:border-primary hover:bg-primary/5 transition-colors aspect-square flex items-center justify-center"
                  @click="canvasFilesInput?.click()"
                  @dragover.prevent
                  @dragenter.prevent
                  @drop.prevent="(e) => handleFileDrop(e, 'canvas')"
                >
                  <div
                    v-if="uploadFiles.canvasFiles.length === 0"
                    class="flex flex-col items-center gap-3"
                  >
                    <FileJsonIcon
                      class="w-12 h-12 text-base-content opacity-40"
                    />
                    <div class="text-sm text-base-content/70 text-center">
                      <div class="font-medium mb-1">点击或拖拽上传</div>
                      <div class="text-xs">支持 .json 文件</div>
                    </div>
                  </div>
                  <div v-else class="flex flex-col items-center gap-2">
                    <FileJsonIcon class="w-8 h-8 text-success" />
                    <div class="text-xs font-medium text-success">
                      {{ uploadFiles.canvasFiles.length }} 个文件
                    </div>
                    <div class="text-xs text-base-content/50">点击重新选择</div>
                  </div>
                </div>
                <input
                  type="file"
                  ref="canvasFilesInput"
                  @change="(e) => handleFileChange(e, 'canvas')"
                  accept=".json"
                  multiple
                  class="hidden"
                />
              </div>
            </div>

            <!-- 第三行：资源包 (单独一个，居中) -->
            <div class="flex justify-center">
              <div class="w-1/2 space-y-2">
                <label class="text-sm font-medium text-base-content"
                  >资源包 (可选)</label
                >
                <div
                  class="border-2 border-dashed border-base-300 rounded-lg p-6 text-center cursor-pointer hover:border-primary hover:bg-primary/5 transition-colors aspect-square flex items-center justify-center"
                  @click="resourceFileInput?.click()"
                  @dragover.prevent
                  @dragenter.prevent
                  @drop.prevent="(e) => handleFileDrop(e, 'resource')"
                >
                  <div
                    v-if="!uploadFiles.resourceFile"
                    class="flex flex-col items-center gap-3"
                  >
                    <FileArchiveIcon
                      class="w-12 h-12 text-base-content opacity-40"
                    />
                    <div class="text-sm text-base-content/70 text-center">
                      <div class="font-medium mb-1">点击或拖拽上传</div>
                      <div class="text-xs">支持 .zip, .rar, .7z 文件</div>
                    </div>
                  </div>
                  <div v-else class="flex flex-col items-center gap-2">
                    <FileArchiveIcon class="w-8 h-8 text-success" />
                    <div class="text-xs font-medium text-success text-center">
                      {{ uploadFiles.resourceFile.name }}
                    </div>
                    <div class="text-xs text-base-content/50">点击重新选择</div>
                  </div>
                </div>
                <input
                  type="file"
                  ref="resourceFileInput"
                  @change="(e) => handleFileChange(e, 'resource')"
                  accept=".zip,.rar,.7z"
                  class="hidden"
                />
              </div>
            </div>
          </div>
        </div>
      </form>
    </div>
    <div class="modal-backdrop" @click="close"></div>
  </div>
</template>

<script setup lang="ts">
import {
  FileTextIcon,
  ImageIcon,
  BinaryIcon,
  FileArchiveIcon,
  FileJsonIcon,
  XIcon,
} from "lucide-vue-next";
import {
  ExamClient,
  ExamDto,
  ResourceClient,
  ResourcePurpose,
  type FileParameter,
} from "@/APIClient";
import { useAlertStore } from "@/components/Alert";
import { AuthManager } from "@/utils/AuthManager";
import { useRequiredInjection } from "@/utils/Common";
import { defineModel, ref, computed } from "vue";
import { mod } from "mathjs";
import type { ExamInfo } from "@/APIClient";

type Mode = "create" | "edit";

const isShowModal = defineModel<boolean>("isShowModal", {
  default: false,
});

const emits = defineEmits<{
  editFinished: [examId: string];
}>();

const alert = useRequiredInjection(useAlertStore);

const editExamInfo = ref({
  id: "",
  name: "",
  description: "",
  tags: [] as string[],
  difficulty: 1,
  isVisibleToUsers: true,
});

const isUpdating = ref(false);
const mode = ref<Mode>("create");
const newTagInput = ref("");

// 文件上传相关
const uploadFiles = ref({
  mdFile: null as File | null,
  imageFiles: [] as File[],
  bitstreamFiles: [] as File[],
  canvasFiles: [] as File[],
  resourceFile: null as File | null,
});

// 文件输入引用
const mdFileInput = ref<HTMLInputElement>();
const imageFilesInput = ref<HTMLInputElement>();
const bitstreamFilesInput = ref<HTMLInputElement>();
const canvasFilesInput = ref<HTMLInputElement>();
const resourceFileInput = ref<HTMLInputElement>();

// 计算属性
const canCreateExam = computed(() => {
  return (
    editExamInfo.value.id.trim() !== "" &&
    editExamInfo.value.name.trim() !== "" &&
    editExamInfo.value.description.trim() !== "" &&
    (mode.value === "edit")
  );
});

// 文件类型定义
type FileType = "md" | "image" | "bitstream" | "canvas" | "resource";

// 统一文件处理方法
const handleFileChange = (event: Event, fileType: FileType) => {
  const target = event.target as HTMLInputElement;
  if (!target.files) return;

  switch (fileType) {
    case "md":
      if (target.files.length > 0) {
        uploadFiles.value.mdFile = target.files[0];
      }
      break;
    case "image":
      uploadFiles.value.imageFiles = Array.from(target.files);
      break;
    case "bitstream":
      uploadFiles.value.bitstreamFiles = Array.from(target.files);
      break;
    case "canvas":
      uploadFiles.value.canvasFiles = Array.from(target.files);
      break;
    case "resource":
      if (target.files.length > 0) {
        uploadFiles.value.resourceFile = target.files[0];
      }
      break;
  }
};

const handleFileDrop = (event: DragEvent, fileType: FileType) => {
  const files = event.dataTransfer?.files;
  if (!files || files.length === 0) return;

  switch (fileType) {
    case "md":
      const mdFile = files[0];
      if (mdFile.name.endsWith(".md")) {
        uploadFiles.value.mdFile = mdFile;
      }
      break;
    case "image":
      const imageFiles = Array.from(files).filter((file) =>
        file.type.startsWith("image/"),
      );
      uploadFiles.value.imageFiles = imageFiles;
      break;
    case "bitstream":
      const bitstreamFiles = Array.from(files).filter(
        (file) =>
          file.name.endsWith(".sbit") ||
          file.name.endsWith(".bit") ||
          file.name.endsWith(".bin"),
      );
      uploadFiles.value.bitstreamFiles = bitstreamFiles;
      break;
    case "canvas":
      const canvasFiles = Array.from(files).filter((file) =>
        file.name.endsWith(".json"),
      );
      uploadFiles.value.canvasFiles = canvasFiles;
      break;
    case "resource":
      const resourceFile = files[0];
      if (
        resourceFile.name.endsWith(".zip") ||
        resourceFile.name.endsWith(".rar") ||
        resourceFile.name.endsWith(".7z")
      ) {
        uploadFiles.value.resourceFile = resourceFile;
      }
      break;
  }
};

// 标签管理
const addTag = (event?: Event) => {
  if (event) {
    event.preventDefault();
    event.stopPropagation();
  }
  const tag = newTagInput.value.trim();
  if (tag && !editExamInfo.value.tags.includes(tag)) {
    editExamInfo.value.tags.push(tag);
    newTagInput.value = "";
  }
};

const removeTag = (index: number) => {
  editExamInfo.value.tags.splice(index, 1);
};

const resetCreateForm = () => {
  editExamInfo.value = {
    id: "",
    name: "",
    description: "",
    tags: [],
    difficulty: 1,
    isVisibleToUsers: true,
  };
  newTagInput.value = "";
  uploadFiles.value = {
    mdFile: null,
    imageFiles: [],
    bitstreamFiles: [],
    canvasFiles: [],
    resourceFile: null,
  };

  // 重置文件输入
  if (mdFileInput.value) mdFileInput.value.value = "";
  if (imageFilesInput.value) imageFilesInput.value.value = "";
  if (bitstreamFilesInput.value) bitstreamFilesInput.value.value = "";
  if (canvasFilesInput.value) canvasFilesInput.value.value = "";
  if (resourceFileInput.value) resourceFileInput.value.value = "";
};

// 提交创建实验
const submitCreateExam = async () => {
  if (isUpdating.value) return;

  // 验证必填字段
  if (
    !editExamInfo.value.id ||
    !editExamInfo.value.name ||
    !editExamInfo.value.description
  ) {
    alert?.error("请填写所有必填字段");
    return;
  }

  isUpdating.value = true;

  try {
    const client = AuthManager.createClient(ExamClient);

    let exam: ExamInfo;
    if (mode.value === "create") {
      // 创建实验请求
      const createRequest = new ExamDto({
        id: editExamInfo.value.id,
        name: editExamInfo.value.name,
        description: editExamInfo.value.description,
        tags: editExamInfo.value.tags,
        difficulty: editExamInfo.value.difficulty,
        isVisibleToUsers: editExamInfo.value.isVisibleToUsers,
      });

      // 创建实验
      exam = await client.createExam(createRequest);
      console.log("实验创建成功:", exam);
    } else if (mode.value === "edit") {
      // 编辑实验请求
      const editRequest = new ExamDto({
        id: editExamInfo.value.id,
        name: editExamInfo.value.name,
        description: editExamInfo.value.description,
        tags: editExamInfo.value.tags,
        difficulty: editExamInfo.value.difficulty,
        isVisibleToUsers: editExamInfo.value.isVisibleToUsers,
      });

      // 编辑实验
      exam = await client.updateExam(editRequest);
      console.log("实验编辑成功:", exam);
    } else {
      // 处理其他模式
      console.error("未知的模式:", mode.value);
      throw new Error("未知的模式");
    }

    // 上传文件
    await uploadExamResources(exam.id);

    alert.success("实验创建成功");
    close();
    emits("editFinished", exam.id);
  } catch (err: any) {
    console.error("创建实验失败:", err);
    alert.error(err.message || "创建实验失败");
  } finally {
    isUpdating.value = false;
  }
};

// 上传实验资源
async function uploadExamResources(examId: string) {
  const client = AuthManager.createClient(ResourceClient);

  try {
    // 上传MD文档
    if (uploadFiles.value.mdFile) {
      const mdFileParam: FileParameter = {
        data: uploadFiles.value.mdFile,
        fileName: uploadFiles.value.mdFile.name,
      };
      await client.addResource(
        "doc",
        ResourcePurpose.Template,
        examId,
        mdFileParam,
      );
      console.log("MD文档上传成功");
    }

    // 上传图片资源
    for (const imageFile of uploadFiles.value.imageFiles) {
      const imageFileParam: FileParameter = {
        data: imageFile,
        fileName: imageFile.name,
      };
      await client.addResource(
        "image",
        ResourcePurpose.Template,
        examId,
        imageFileParam,
      );
      console.log("图片上传成功:", imageFile.name);
    }

    // 上传比特流文件
    for (const bitstreamFile of uploadFiles.value.bitstreamFiles) {
      const bitstreamFileParam: FileParameter = {
        data: bitstreamFile,
        fileName: bitstreamFile.name,
      };
      await client.addResource(
        "bitstream",
        ResourcePurpose.Template,
        examId,
        bitstreamFileParam,
      );
      console.log("比特流文件上传成功:", bitstreamFile.name);
    }

    // 上传画布模板
    for (const canvasFile of uploadFiles.value.canvasFiles) {
      const canvasFileParam: FileParameter = {
        data: canvasFile,
        fileName: canvasFile.name,
      };
      await client.addResource(
        "canvas",
        ResourcePurpose.Template,
        examId,
        canvasFileParam,
      );
      console.log("画布模板上传成功:", canvasFile.name);
    }

    // 上传资源包
    if (uploadFiles.value.resourceFile) {
      const resourceFileParam: FileParameter = {
        data: uploadFiles.value.resourceFile,
        fileName: uploadFiles.value.resourceFile.name,
      };
      await client.addResource(
        "resource",
        ResourcePurpose.Template,
        examId,
        resourceFileParam,
      );
      console.log("资源包上传成功");
    }
  } catch (err: any) {
    console.error("资源上传失败:", err);
    alert?.error("部分资源上传失败: " + (err.message || "未知错误"));
  }
}

function show() {
  isShowModal.value = true;
}

function close() {
  isShowModal.value = false;
  mode.value = "create";
  resetCreateForm();
}

async function editExam(examId: string) {
  const client = AuthManager.createClient(ExamClient);
  const examInfo = await client.getExam(examId);

  editExamInfo.value = {
    id: examInfo.id,
    name: examInfo.name,
    description: examInfo.description,
    tags: examInfo.tags,
    difficulty: examInfo.difficulty,
    isVisibleToUsers: examInfo.isVisibleToUsers,
  };

  mode.value = "edit";
  show();
}

defineExpose({
  show,
  close,
  editExam,
  editExamInfo,
});
</script>

<style lang="postcss" scoped></style>
