<template>
  <div class="quick-submit">
    <el-card shadow="never">
      <template #header>
        <span class="card-title">{{ isEdit ? '编辑工单' : $t('modal.submit') }}</span>
      </template>

      <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-width="120px"
      >
        <el-form-item :label="$t('label.title')" prop="title">
          <div class="title-row">
            <el-input
              v-model="form.title"
              :placeholder="$t('placeholder.title')"
              maxlength="100"
              show-word-limit
            />
            <div class="color-tag-picker" ref="colorPickerRef">
              <div
                class="color-tag-preview"
                :style="{ background: form.colorTag || '#dcdfe6' }"
                :class="{ 'is-empty': !form.colorTag }"
                @click.stop="toggleColorPicker"
              ></div>
              <div
                v-show="colorPickerVisible"
                class="color-tag-dropdown"
                @click.stop
              >
                <div class="color-tag-title">{{ $t('label.colorTag') }}</div>
                <div class="color-tag-options">
                  <div
                    v-for="c in colorOptions"
                    :key="c.value"
                    class="color-tag-option"
                    :class="{ active: form.colorTag === c.value }"
                    :style="{ background: c.value }"
                    :title="c.label"
                    @click="selectColor(c.value)"
                  ></div>
                </div>
              </div>
            </div>
          </div>
        </el-form-item>
        <el-form-item :label="$t('label.type')" prop="serviceType">
          <el-select
            v-model="form.serviceType"
            :placeholder="$t('placeholder.type')"
            clearable
            style="width: 240px"
          >
            <el-option label="故障报修" value="故障报修" />
            <el-option label="业务咨询" value="业务咨询" />
            <el-option label="需求变更" value="需求变更" />
            <el-option label="其他" value="其他" />
          </el-select>
        </el-form-item>
        <el-form-item label-width="0">
          <div class="inline-row">
            <el-form-item :label="$t('label.priority')" prop="priority" class="inline-item">
              <el-radio-group v-model="form.priority">
                <el-radio-button label="高">高</el-radio-button>
                <el-radio-button label="中">中</el-radio-button>
                <el-radio-button label="低">低</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item :label="$t('label.feedbackchannel')" prop="feedbackchannel" class="inline-item">
              <el-select
                v-model="form.feedbackchannel"
                :placeholder="$t('placeholder.feedbackchannel')"
                clearable
                style="width: 200px"
              >
                <el-option label="微信群" value="微信群" />
                <el-option label="微信" value="微信" />
                <el-option label="电话" value="电话" />
                <el-option label="现场" value="现场" />
                <el-option label="钉钉群" value="钉钉群" />
                <el-option label="钉钉" value="钉钉" />
                <el-option label="其他" value="其他" />
              </el-select>
            </el-form-item>
          </div>
        </el-form-item>
        <el-form-item :label="$t('label.dept')" prop="department">
          <el-input
            v-model="form.department"
            :placeholder="$t('placeholder.dept')"
          />
        </el-form-item>
        <el-form-item :label="$t('label.name')" prop="submitter">
          <el-input
            v-model="form.submitter"
            :placeholder="$t('placeholder.name')"
          />
        </el-form-item>
        <el-form-item :label="$t('label.createat')" prop="createdat">
          <el-date-picker
            v-model="form.createdat"
            type="datetime"
            :placeholder="$t('placeholder.createat')"
            value-format="YYYY-MM-DD HH:mm:ss"
            format="YYYY-MM-DD HH:mm:ss"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item :label="$t('label.description')" prop="description">
          <div class="rich-editor">
            <Toolbar
              :editor="editorRef"
              :default-config="toolbarConfig"
              mode="default"
              style="border-bottom: 1px solid #dcdfe6"
            />
            <Editor
              v-model="form.description"
              :default-config="editorConfig"
              mode="default"
              style="height: 200px; overflow-y: auto"
              @on-created="handleEditorCreated"
              @custom-paste="handleEditorPasteImage"
            />
          </div>
        </el-form-item>
        <el-form-item class="fujian" :label="$t('label.attachment')">
          <el-upload
            v-model:file-list="form.files"
            :auto-upload="false"
            :limit="1"
            :on-exceed="handleAttachmentExceed"
            :on-remove="handleAttachmentRemove"
            :on-change="handleAttachmentChange"
          >
            <el-button type="primary" plain>{{ $t('btn.upload') }}</el-button>
            <template #tip>
              <div class="el-upload__tip">
                {{ $t('label.attachmentTip') }}
              </div>
            </template>
          </el-upload>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :loading="submitting" @click="submit">{{ $t('common.submit') }}</el-button>
          <el-button @click="onCancel">{{ $t('common.cancel') }}</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 提交工单后 +1 积分奖励弹窗 -->
    <el-dialog
      v-model="rewardVisible"
      width="360px"
      :show-close="false"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      append-to-body
      class="reward-dialog"
    >
      <div class="reward-content">
        <div class="reward-badge">✦ 奖励已发放</div>
        <div class="coin-wrapper">
          <span class="reward-coin">🪙</span>
        </div>
        <div class="points-number">
          +1 <small>积分</small>
        </div>
        <div class="reward-title">🎉 到账通知</div>
        <div class="reward-sub">1 积分已放入您的钱包</div>

        <div class="reward-progress">
          <div class="reward-progress-label">
            <span>🏆 距兑换「康小虎 AI 吉祥物」</span>
            <span class="reward-distance">
              <template v-if="rewardDistance > 0">
                还差 {{ rewardDistance }} 分
              </template>
              <template v-else>已达标 🎉</template>
            </span>
          </div>
          <div class="reward-bar-bg">
            <div
              class="reward-bar-fill"
              :style="{ width: rewardProgress + '%' }"
            ></div>
          </div>
          <div class="reward-current">
            当前 {{ rewardTotalPoints }} 分
          </div>
        </div>

        <div class="reward-actions">
          <el-button class="reward-btn reward-btn-received" @click="onRewardClose">
            开心收下
          </el-button>
          <el-button class="reward-btn reward-btn-assets" type="warning" @click="goMyAssets">
            查看我的资产 →
          </el-button>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import dayjs from "dayjs";
import {
  nextTick,
  onBeforeUnmount,
  reactive,
  ref,
  shallowRef,
  computed,
  watch,
  onMounted,
} from "vue";
import { useRouter,useRoute } from "vue-router";
import { ElMessage } from "element-plus";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import "@wangeditor/editor/dist/css/style.css";
import { useI18n } from "vue-i18n";
import {
  createHospitalOrder,
  getHospitalOrderDetail,
  updateHospitalOrder,
  getPoints,
} from "@/service/modular/hospital";

// 兑换目标(与 points 页保持一致)
const EXCHANGE_GOAL = 500;

const { t: $t } = useI18n();
const route = useRoute();
const router = useRouter();
const formRef = ref();
const submitting = ref(false);

// 编辑模式：url 带 :id 参数
const isEdit = computed(() => !!route.params.id);
const editId = computed(() => route.params.id);

// 从带路径分隔符的地址中截取最后的文件名
const getAttachmentFileName = (path) => {
  if (!path) return "";
  return String(path).replace(/\\/g, "/").split("/").pop() || "";
};

// 已加载的原始附件 filePath 集合（用于判断用户是否需要保留原附件）
const originalAttachments = ref([]);

// 根据后端返回填充表单（编辑模式）
const fillFormFromDetail = (detail) => {
  if (!detail) return;
  form.title = detail.title || "";
  form.serviceType = detail.serviceType || "";
  form.priority = detail.priority || "中";
  form.feedbackchannel = detail.feedbackChannel || "";
  form.department = detail.department || "";
  form.colorTag = detail.colorTag || "#667eea";
  form.description = detail.description || "";
  form.submitter = detail.submitter || "";
  form.createdat = detail.createdAt
    ? dayjs(detail.createdAt).format("YYYY-MM-DD HH:mm:ss")
    : "";
  // 附件回显：把详情里的第一个附件作为 el-upload 的“已上传”项展示
  const atts = detail.attachments || [];
  originalAttachments.value = atts.map((a) => a.filePath).filter(Boolean);
  if (atts.length) {
    const first = atts[0];
    const fileName = first.fileName || getAttachmentFileName(first.filePath);
    if (fileName) {
      form.files = [
        {
          uid: `attachment-${editId.value}-0`,
          name: fileName,
          status: "success",
        },
      ];
      return;
    }
  }
  form.files = [];
};

const loadDetail = async (id) => {
  try {
    const res = await getHospitalOrderDetail(id);
    fillFormFromDetail(res);
  } catch (_) {
    ElMessage.error("加载工单详情失败");
  }
};

// id 变化时重新加载（同一组件跨路由复用场景）
watch(
  () => route.params.id,
  (id) => {
    if (id) {
      loadDetail(id);
    }
  },
);

const form = reactive({
  title: "",
  serviceType: "",
  priority: "中",
  feedbackchannel: "",
  department: "",
  colorTag: "#667eea",
  description: "",
  submitter: "",
  createdat: "",
  files: [],
});

const rules = {
  title: [{ required: true, message: () => $t('msg.pleaseInputTitle'), trigger: "blur" }],
  serviceType: [{ required: true, message: () => $t('msg.pleaseSelectType'), trigger: "change" }],
  priority: [{ required: true, message: () => $t('msg.pleaseSelectPriority'), trigger: "change" }],
  feedbackchannel: [
    { required: true, message: () => $t('msg.pleaseSelectFeedbackChannel'), trigger: "change" },
  ],
  department: [
    { required: true, whitespace: true, message: () => $t('msg.pleaseInputDept'), trigger: "blur" },
  ],
  submitter: [
    { required: true, whitespace: true, message: () => $t('msg.pleaseInputName'), trigger: "blur" },
  ],
  description: [
    {
      required: true,
      validator: (_, value, callback) => {
        const hasImage = /<img\s/i.test(value || "");
        const text = (value || "")
          .replace(/<[^>]*>/g, "")
          .replace(/&nbsp;/gi, "")
          .trim();
        if (!text && !hasImage) return callback(new Error($t('msg.pleaseInputDescription')));
        callback();
      },
      trigger: "change",
    },
  ],
};

// 颜色标签可选值
const colorOptions = [
  { label: "蓝", value: "#667eea" },
  { label: "绿", value: "#52c41a" },
  { label: "青", value: "#13c2c2" },
  { label: "紫", value: "#722ed1" },
  { label: "橙", value: "#fa8c16" },
  { label: "红", value: "#ff4d4f" },
];
const colorPickerVisible = ref(false);
const colorPickerRef = ref();
const toggleColorPicker = () => {
  colorPickerVisible.value = !colorPickerVisible.value;
};
const selectColor = (val) => {
  form.colorTag = val;
  colorPickerVisible.value = false;
};
const onDocClick = (e) => {
  if (!colorPickerVisible.value) return;
  const el = colorPickerRef.value;
  if (el && !el.contains(e.target)) {
    colorPickerVisible.value = false;
  }
};

const MAX_FILE_SIZE = 50 * 1024 * 1024;
const MAX_PASTE_IMAGE_SIZE = 5 * 1024 * 1024;

const handleAttachmentChange = (file) => {
  if (file?.size > MAX_FILE_SIZE) {
    ElMessage.warning("文件不能超过 50MB");
    form.files = form.files.filter(
      (f) => f.uid !== file.uid || f.size <= MAX_FILE_SIZE,
    );
  }
};
const handleAttachmentExceed = () => {
  ElMessage.warning("只能上传 1 个文件");
};
const handleAttachmentRemove = () => {
  // el-upload 会自动从 v-model:file-list 移除
};

const nowDatetime = () => dayjs().format("YYYY-MM-DD HH:mm:ss");

// 富文本编辑器配置
const editorRef = shallowRef();
const toolbarConfig = {
  excludeKeys: [
    "uploadImage",
    "insertVideo",
    "uploadVideo",
    "group-video",
    "emotion",
    "group-emoji",
  ],
};

const collectPastedImages = (clipboardData) => {
  const files = [];
  const items = clipboardData?.items;
  if (items) {
    for (let i = 0; i < items.length; i++) {
      const item = items[i];
      if (item.kind === "file" && item.type?.startsWith("image/")) {
        const file = item.getAsFile();
        if (file) files.push(file);
      }
    }
  }
  if (files.length === 0 && clipboardData?.files) {
    for (let i = 0; i < clipboardData.files.length; i++) {
      const file = clipboardData.files[i];
      if (file.type?.startsWith("image/")) files.push(file);
    }
  }
  return files;
};

const handleEditorPasteImage = (editor, event) => {
  if (event.__wpsImageHandled) return;
  const imageFiles = collectPastedImages(event.clipboardData);
  if (imageFiles.length === 0) return;
  event.__wpsImageHandled = true;
  event.preventDefault();
  if (typeof event.stopPropagation === "function") event.stopPropagation();
  if (typeof event.stopImmediatePropagation === "function")
    event.stopImmediatePropagation();

  if (typeof editor.focus === "function") editor.focus();
  const savedSelection = editor.selection;

  imageFiles.forEach((file) => {
    if (file.size > MAX_PASTE_IMAGE_SIZE) {
      ElMessage.warning("粘贴的图片不能超过 5MB");
      return;
    }
    const reader = new FileReader();
    reader.onload = (e) => {
      const dataUrl = e.target?.result;
      if (!dataUrl) {
        ElMessage.error("图片读取失败");
        return;
      }
      try {
        if (savedSelection) editor.select(savedSelection);
      } catch (_) {
        if (typeof editor.focus === "function") editor.focus();
      }
      if (typeof editor.focus === "function") editor.focus();
      editor.dangerouslyInsertHtml(
        `<img src="${dataUrl}" style="max-width:100%;height:auto;" />`,
      );
      if (typeof editor.updateView === "function") editor.updateView();
    };
    reader.onerror = () => {
      ElMessage.error("图片处理失败");
    };
    reader.readAsDataURL(file);
  });
  return false;
};

const editorConfig = {
  placeholder: $t('placeholder.description'),
};
let pasteHandlerRef = null;
const handleEditorCreated = (editor) => {
  editorRef.value = editor;
  nextTick(() => {
    const root = typeof editor.$el === "function" ? editor.$el() : editor.$el;
    if (!root) return;
    const editable = root.querySelector?.('[contenteditable="true"]') || root;
    if (pasteHandlerRef) {
      editable.removeEventListener("paste", pasteHandlerRef, { capture: true });
    }
    pasteHandlerRef = (event) => handleEditorPasteImage(editor, event);
    editable.addEventListener("paste", pasteHandlerRef, { capture: true });
  });
};

// ============== 提交后奖励弹窗 ==============
// 后端在创建工单时已自动 +1 积分，这里仅刷新最新积分并提示用户
const rewardVisible = ref(false);
const rewardTotalPoints = ref(0);
const rewardProgress = ref(0); // 进度条宽度 (%)
const rewardDistance = ref(0); // 还差多少分

const playCoinAnimation = () => {
  // 重播动画:先移除 class 再加回去（仅做 minimal 动画）
  nextTick(() => {
    const coin = document.querySelector(".reward-coin");
    if (!coin) return;
    coin.classList.remove("spin");
    void coin.offsetWidth;
    coin.classList.add("spin");
  });
};

const showRewardDialog = async () => {
  let total = 0;
  try {
    const res = await getPoints();
    const data = res?.data ?? res ?? {};
    total = Number(data.totalPoints) || 0;
  } catch (_) {
    // 刷新失败不阻塞
  }
  rewardTotalPoints.value = total;
  rewardProgress.value = Math.min(100, Math.round((total / EXCHANGE_GOAL) * 100));
  rewardDistance.value = Math.max(0, EXCHANGE_GOAL - total);
  rewardVisible.value = true;
  playCoinAnimation();
};

const onRewardClose = () => {
  rewardVisible.value = false;
  router.replace("/hospital/orders");
};

const goMyAssets = () => {
  rewardVisible.value = false;
  router.replace("/hospital/points");
};

const submit = async () => {
  form.department = (form.department || "").trim();
  form.submitter = (form.submitter || "").trim();
  await formRef.value.validate(async (valid) => {
    if (!valid) return;
    submitting.value = true;
    try {
      const formData = new FormData();
      const { files, ...rest } = form;
      for (const [k, v] of Object.entries(rest)) {
        if (v !== undefined && v !== null && v !== "") {
          formData.append(k, v);
        }
      }
      for (const f of files || []) {
        if (f.raw) formData.append("files", f.raw, f.name);
      }
      if (isEdit.value) {
        await updateHospitalOrder(editId.value, formData);
        ElMessage.success("编辑成功");
        router.replace("/hospital/orders");
      } else {
        await createHospitalOrder(formData);
        ElMessage.success($t('msg.submitSuccess'));
        // 新建成功 → 弹出 +1 积分奖励提示，后端已自动加分
        showRewardDialog();
      }
    } finally {
      submitting.value = false;
    }
  });
};

const onCancel = () => router.back();

onMounted(() => {
  document.addEventListener("click", onDocClick);
  if (isEdit.value) {
    // 编辑模式：加载详情填充表单
    loadDetail(editId.value);
  } else {
    // 新增模式：默认提交时间为当前时间
    form.createdat = nowDatetime();
  }
});

const removePasteListener = () => {
  const editor = editorRef.value;
  if (!editor || !pasteHandlerRef) return;
  const root = typeof editor.$el === "function" ? editor.$el() : editor.$el;
  if (!root) return;
  const editable = root.querySelector?.('[contenteditable="true"]') || root;
  editable.removeEventListener("paste", pasteHandlerRef, { capture: true });
};

onBeforeUnmount(() => {
  document.removeEventListener("click", onDocClick);
  removePasteListener();
  pasteHandlerRef = null;
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});
</script>

<style scoped lang="scss">
.quick-submit {
  :deep(.el-card) {
    max-width: 100%;
  }
  .el-form {
    max-width: 100%;
  }
}
.card-title {
  font-size: 16px;
  font-weight: 600;
}
.rich-editor {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  width: 100%;
  overflow: hidden;
  background: #fff;
}
.rich-editor :deep(.w-e-toolbar) {
  background: #fafafa;
}

// 标题 + 颜色标签
.title-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
}
.title-row .el-input {
  flex: 1;
}
// 优先级 + 反馈渠道同一行展示
.inline-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 24px;
  width: 100%;
}
.inline-row .inline-item {
  margin-bottom: 0 !important;
}
.inline-row .inline-item :deep(.el-form-item__content) {
  display: flex;
  align-items: center;
}
.color-tag-picker {
  position: relative;
  flex-shrink: 0;
}
.color-tag-preview {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  cursor: pointer;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
  transition:
    transform 0.2s ease,
    box-shadow 0.2s ease;
}
.color-tag-preview:hover {
  transform: scale(1.08);
}
.color-tag-preview.is-empty {
  background-image: linear-gradient(
    135deg,
    #f5f5f5 25%,
    transparent 25%,
    transparent 50%,
    #f5f5f5 50%,
    #f5f5f5 75%,
    transparent 75%
  );
  background-size: 8px 8px;
  box-shadow: 0 0 0 1px #dcdfe6;
}
.color-tag-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 10;
  background: #fff;
  border-radius: 10px;
  padding: 12px 14px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  min-width: 180px;
}
.color-tag-title {
  font-size: 13px;
  font-weight: 600;
  color: #333;
  margin-bottom: 10px;
}
.color-tag-options {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.color-tag-option {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  cursor: pointer;
  border: 2px solid transparent;
  transition:
    transform 0.2s ease,
    border-color 0.2s ease;
}
.color-tag-option:hover {
  transform: scale(1.12);
}
.color-tag-option.active {
  border-color: #1890ff;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}

// 限制上传文件预览盒子宽度溢出
:deep(.fujian .el-form-item__content > div) {
  width: 100% !important;
}

// ============== 提交后奖励弹窗 ==============
:deep(.reward-dialog) {
  .el-dialog__header {
    display: none;
  }
  .el-dialog__body {
    padding: 0;
  }
}
.reward-content {
  text-align: center;
  padding: 24px 24px 22px;
}
.reward-badge {
  display: inline-block;
  background: #fef3e6;
  color: #c47a2e;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 16px;
  border-radius: 40px;
  margin-bottom: 8px;
}
.coin-wrapper {
  height: 80px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 4px;
}
.reward-coin {
  font-size: 64px;
  display: inline-block;
  filter: drop-shadow(0 8px 16px rgba(255, 193, 7, 0.3));
}
.reward-coin.spin {
  animation: rewardCoinSpin 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
@keyframes rewardCoinSpin {
  0% {
    transform: rotateY(0deg) scale(0.2);
    opacity: 0;
  }
  60% {
    transform: rotateY(720deg) scale(1.2);
    opacity: 1;
  }
  100% {
    transform: rotateY(720deg) scale(1);
    opacity: 1;
  }
}
.points-number {
  font-size: 48px;
  font-weight: 800;
  color: #f5a623;
  line-height: 1.1;
  margin-top: -4px;
}
.points-number small {
  font-size: 20px;
  font-weight: 600;
  color: #b8863a;
}
.reward-title {
  font-size: 22px;
  font-weight: 700;
  color: #1f140e;
  margin: 4px 0 6px;
}
.reward-sub {
  font-size: 14px;
  color: #7a6a5c;
  margin-bottom: 16px;
}
.reward-progress {
  background: #f8f4f0;
  border-radius: 16px;
  padding: 14px 16px;
  margin-bottom: 18px;
  text-align: left;
}
.reward-progress-label {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: #4d3e32;
  font-weight: 500;
  gap: 8px;
}
.reward-distance {
  color: #f5a623;
  font-weight: 700;
  flex-shrink: 0;
}
.reward-bar-bg {
  width: 100%;
  height: 6px;
  background: #e6ddd5;
  border-radius: 10px;
  margin-top: 8px;
  overflow: hidden;
}
.reward-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #f9b84a, #f5a623);
  border-radius: 10px;
  transition: width 0.6s ease;
}
.reward-current {
  margin-top: 8px;
  font-size: 12px;
  color: #8a7a6a;
  text-align: right;
}
.reward-actions {
  display: flex;
  gap: 10px;
}
.reward-btn {
  flex: 1;
  padding: 12px 0 !important;
  font-size: 14px !important;
  font-weight: 600 !important;
  border-radius: 60px !important;
}
.reward-btn-received {
  background: #f0ebe6 !important;
  border-color: #f0ebe6 !important;
  color: #4d3e32 !important;
}
.reward-btn-received:hover {
  background: #e6ddd5 !important;
  border-color: #e6ddd5 !important;
}
.reward-btn-assets {
  background: #f9b84a !important;
  border-color: #f9b84a !important;
  color: #1f140e !important;
  box-shadow: 0 4px 14px rgba(249, 184, 74, 0.25);
}
.reward-btn-assets:hover {
  background: #f5ac2e !important;
  border-color: #f5ac2e !important;
  transform: translateY(-1px);
}
</style>
