﻿<template>
  <el-dialog :model-value="modelValue" class="hospital-order-form-dialog" :close-on-click-modal="true"
    @update:model-value="(v) => $emit('update:modelValue', v)" @closed="onClosed">
    <div class="body-wrap">
      <div class="body-header">
        <div class="body-title">{{ isEdit() ? '编辑工单' : '新建工单' }}</div>
        <img src="@/assets/image/close-btn.svg" alt="" class="close-btn" @click="onCancel" />
      </div>

      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <!-- 第一行 2 列：服务类型 + 反馈渠道（医院端没有"所属医院"） -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item :label="$t('label.type')" prop="serviceType">
              <el-select v-model="form.serviceType" :placeholder="$t('placeholder.type')" clearable style="width: 100%">
                <el-option label="故障报修" value="故障报修" />
                <el-option label="业务咨询" value="业务咨询" />
                <el-option label="需求变更" value="需求变更" />
                <el-option label="其他" value="其他" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="$t('label.feedbackchannel')" prop="feedbackchannel">
              <el-select v-model="form.feedbackchannel" :placeholder="$t('placeholder.feedbackchannel')" clearable
                style="width: 100%">
                <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>
          </el-col>
        </el-row>
        <!-- 第二行 3 列：科室 + 提单人 + 提交时间 -->
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item :label="$t('label.dept')" prop="department">
              <el-input v-model="form.department" :placeholder="$t('placeholder.dept')" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item :label="$t('label.name')" prop="submitter">
              <el-input v-model="form.submitter" :placeholder="$t('placeholder.name')" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <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-col>
        </el-row>
        <!-- 标题 + 颜色标签 + 优先级 同一行 -->
        <el-form-item :label="$t('label.title')" prop="title">
          <div class="title-row">
            <el-input v-model="form.title" :placeholder="$t('placeholder.title')" maxlength="300" class="title-input">
              <template #suffix>
                <span class="title-counter"><span :style="{ color: form.colorTag || '#dcdfe6' }">{{ form.title.length
                    }}</span>/300</span>
                <el-popover v-model:visible="colorPickerVisible" :width="180" placement="bottom-end" trigger="click"
                  :show-arrow="false" popper-class="color-tag-popper">
                  <template #reference>
                    <el-badge :color="form.colorTag || '#dcdfe6'" is-dot class="item">
                      <img src="@/assets/image/admin/orders/sepan.svg" alt="" class="title-sepan" />
                    </el-badge>
                  </template>
                  <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>
                </el-popover>
              </template>
            </el-input>
            <div class="priority-wrap">
              <div class="priority-label">{{ $t('label.priority') }}</div>
              <el-select v-model="form.priority" class="priority-select" :teleported="false">
                <template #label="{ label, value }">
                  <div class="priority-row high" v-if="value === '高'">{{ value }}</div>
                  <div class="priority-row medium" v-if="value === '中'">{{ value }}</div>
                  <div class="priority-row low" v-if="value === '低'">{{ value }}</div>
                </template>
                <el-option v-for="opt in priorityOptions" :key="opt.value" :value="opt.value">
                  <span class="priority-option">
                    <span class="priority-dot" :class="opt.cls"></span>
                    <span class="priority-option-label">{{ opt.label }}</span>
                  </span>
                </el-option>
              </el-select>
            </div>
          </div>
        </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 class="upload-wrap" v-model:file-list="form.files" :auto-upload="false" :limit="1"
            :on-exceed="handleAttachmentExceed" :on-remove="handleAttachmentRemove" :on-change="handleAttachmentChange">
            <div class="upload-btn">
              <div class="left">+ 添加文件</div>
              <div class="right">{{ $t('label.attachmentTip') }}</div>
            </div>
            <template #file="{ file }">
              <div class="file-item">
                <img class="file-icon" src="@/assets/image/admin/orders/file.svg" alt="">
                <div class="file-name">&nbsp;&nbsp;{{ file.name }}</div>
                <div class="file-size">&nbsp;&nbsp;{{ ((file.size || 0) / 1024 / 1024).toFixed(2) }}MB</div>
                <div class="file-delete" @click="handleAttachmentDelete(file)">删除</div>
              </div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
    </div>
    <div class="body-footer">
      <el-button @click="onCancel">{{ $t('common.cancel') }}</el-button>
      <el-button type="primary" :loading="submitting" @click="submit">
        {{ $t('common.submit') }}
      </el-button>
    </div>
  </el-dialog>
</template>

<script setup>
import dayjs from "dayjs";
import {
  nextTick,
  onBeforeUnmount,
  reactive,
  ref,
  shallowRef,
  watch,
} from "vue";
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";
import { useRewardResultStore } from "@/stores/rewardResult";
import iconSubmit from "@/assets/image/hospital/ponits/icon-submit-large.svg";

const props = defineProps({
  modelValue: { type: Boolean, default: false },
  orderId: { type: [String, Number], default: null },
});
const emit = defineEmits(["update:modelValue", "success"]);

const { t: $t } = useI18n();

const isEdit = () => !!props.orderId;
const formRef = ref();
const submitting = ref(false);

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

const rewardResultStore = useRewardResultStore();

const getAttachmentFileName = (path) => {
  if (!path) return "";
  return String(path).replace(/\\/g, "/").split("/").pop() || "";
};

// 根据后端返回填充表单（编辑模式）
const fillFormFromDetail = (detail) => {
  if (!detail) return;
  form.title = detail.title || "";
  form.serviceType = detail.serviceType || "";
  form.priority = detail.priority || "中";
  form.feedbackchannel = detail.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")
    : "";
  // 附件回显
  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-${props.orderId}-0`,
          name: fileName,
          status: "success",
          size: first.fileSize || 0,
        },
      ];
      return;
    }
  }
  form.files = [];
};

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

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 selectColor = (val) => {
  form.colorTag = val;
  colorPickerVisible.value = false;
};

// 优先级可选值（带高/中/低配色 cls）
const priorityOptions = [
  { label: "高", value: "高", cls: "high" },
  { label: "中", value: "中", cls: "medium" },
  { label: "低", value: "低", cls: "low" },
];

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 handleAttachmentDelete = (file) => {
  // 自定义"删除"按钮：按 uid 从 form.files 中移除（与 admin 端保持一致）
  form.files = (form.files || []).filter((f) => f.uid !== file?.uid);
};

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 });
  });
};

// ============== 取最新积分 ==============
const fetchLatestPoints = async () => {
  try {
    const res = await getPoints();
    const data = res?.data ?? res ?? {};
    return Number(data.totalPoints) || 0;
  } catch (_) {
    return 0;
  }
};

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()) {
        await updateHospitalOrder(props.orderId, formData);
        ElMessage.success("编辑成功");
        emit("update:modelValue", false);
        emit("success", { isEdit: true });
      } else {
        await createHospitalOrder(formData);
        ElMessage.success($t('msg.submitSuccess'));
        // 取最新积分,关闭自己,打开全局奖励结果弹窗
        const totalPoints = await fetchLatestPoints();
        emit("update:modelValue", false);
        setTimeout(() => {
          rewardResultStore.open({
            title: "提交工单",
            icon: iconSubmit,
            points: 1,
            batchGoal: 500,
            batchCurrent: totalPoints,
            rewardName: "康小虎 AI 吉祥物",
          });
        }, 100);
        emit("success", { isCreate: true });
      }
    } finally {
      submitting.value = false;
    }
  });
};

const onCancel = () => {
  emit("update:modelValue", false);
};

const onClosed = () => {
  // 关闭时重置表单（编辑模式下重新打开会重新加载详情）
  form.title = "";
  form.serviceType = "";
  form.priority = "中";
  form.feedbackchannel = "";
  form.department = "";
  form.colorTag = "#667eea";
  form.description = "";
  form.submitter = "";
  form.createdat = "";
  form.files = [];
  originalAttachments.value = [];
};

// 打开时根据 orderId 决定加载模式
watch(
  () => [props.modelValue, props.orderId],
  ([visible, id]) => {
    if (!visible) return;
    if (id) {
      loadDetail(id);
    } 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(() => {
  removePasteListener();
  pasteHandlerRef = null;
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});
</script>

<style lang="scss">
.hospital-order-form-dialog {
  .rich-editor {
    width: 100%;
    background: #fff;
    border-radius: 4px;
    border: 1px solid #dcdfe6;
    overflow: hidden;
  }

  .rich-editor :deep(.w-e-toolbar) {
    background: #fafafa;
    border-bottom: 1px solid #dcdfe6;
  }

  .rich-editor :deep(.w-e-text-container) {
    background: #fff;
  }

  .priority-row {
    &.high {
      --current-color: #ff383c;
      background: #ffebec;
    }

    &.medium {
      --current-color: #ff8d28;
      background: #ffefe2;
    }

    &.low {
      --current-color: #3289fb;
      background: #eaf3ff;
    }

    width: 50px;
    height: 30px;
    border-radius: 8px 8px 8px 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;

    &::before {
      content: "";
      display: block;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: var(--current-color);
    }

    color: var(--current-color);
  }

  // 标题 + 颜色标签 + 优先级 同一行（与 admin 端一致）
  .title-row {
    display: flex;
    align-items: center;
    width: 100%;
  }

  .title-row .title-input {
    flex: 1;

    .el-input__wrapper {
      border-top-right-radius: 0px;
      border-bottom-right-radius: 0px;
    }
  }

  .title-row :deep(.el-input__suffix) {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .title-counter {
    font-size: 13px;
    color: #909399;
    margin-right: 10px;
  }

  .title-sepan {
    width: 16px;
    height: 16px;
    display: block;
    cursor: pointer;
  }

  .color-tag-picker {
    position: relative;
    flex-shrink: 0;
  }

  // 优先级（与 admin 端一致：左 label + 右 select 拼接）
  .priority-wrap {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    border-radius: 8px;
    height: 40px;
  }

  .priority-label {
    height: 40px;
    border-top: 1px solid #ebeef5;
    border-bottom: 1px solid #ebeef5;
    background: #F9FAFF;
    color: #BCBCBC;
    font-weight: 400;
    font-size: 14px;
    white-space: nowrap;
    padding: 0 14px;
    line-height: 40px;
  }

  .priority-select {
    width: 110px;
  }

  .priority-select .el-select__wrapper {
    background: transparent;
    padding: 5px 13px;
    display: flex;
    justify-content: space-between;
    border-top-left-radius: 0px;
    border-bottom-left-radius: 0px;
  }

  .priority-select :deep(.el-select__placeholder) {
    color: #303133;
  }

  .priority-option {
    display: inline-flex;
    align-items: center;
    gap: 8px;
  }

  .priority-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
  }

  .priority-dot.high {
    background: #ff383c;
  }

  .priority-dot.medium {
    background: #ff8d28;
  }

  .priority-dot.low {
    background: #3289fb;
  }

  .priority-option-label {
    font-size: 14px;
    color: #303133;
  }

  :deep(.fujian .el-form-item__content > div) {
    width: 100% !important;
  }
}
</style>

<style lang="scss">
.hospital-order-form-dialog {
  max-width: 90vw;
  width: 1168px;
  overflow: visible;

  .body-footer {
    border-radius: 0 0 24px 24px;
  }

  --el-component-size: 40px;

  .el-select__wrapper {
    height: 40px;
  }

  .fujian {
    .upload-wrap {
      width: 100%;

      .el-upload-list__item {
        &:hover {
          background: transparent;
        }

        .file-item {
          display: flex;
          align-items: center;
          font-weight: 400;
          font-size: 14px;

          .file-icon {
            width: 18px;
            height: 18px;
          }

          .file-name,
          .file-delete {
            color: #1D2129;

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

          .file-delete {
            margin-left: 14px;
            cursor: pointer;
          }

          .file-size {
            color: #BCBCBC;
          }
        }
      }
    }

    .upload-btn {
      display: flex;
      align-items: center;

      .left {
        font-weight: 400;
        font-size: 14px;
        color: #2B324C;
      }

      .right {
        font-weight: 400;
        font-size: 14px;
        color: #666666;
      }
    }
  }
}

// 颜色标签 popover 内容（默认 teleport 到 body，需放非 scoped 样式块）
.color-tag-popper {
  padding: 12px 14px !important;
  border-radius: 10px !important;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12) !important;
  min-width: 180px;
}
</style>
