<template>
  <el-dialog :model-value="modelValue" class="admin-order-form-dialog" :close-on-click-modal="false"
    @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="closeDialog" />
      </div>

      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" v-loading="formLoading">
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item :label="'所属医院'" prop="hospitalId">
              <el-select v-model="form.hospitalId" :placeholder="$t('msg.pleaseSelectHospital')" filterable
                style="width: 100%">
                <el-option v-for="h in hospitals" :key="h.id" :label="h.name" :value="h.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item :label="$t('label.type')" prop="serviceType">
              <el-select v-model="form.serviceType" :placeholder="$t('placeholder.type')" clearable>
                <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="8">
            <el-form-item :label="$t('label.feedbackchannel')" prop="feedbackchannel">
              <el-select v-model="form.feedbackchannel" :placeholder="$t('placeholder.feedbackchannel')" clearable>
                <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>
        <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>

                <div class="color-tag-picker">
                  <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>
                </div>
              </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 / 1024 / 1024).toFixed(2) }}MB</div>
                <!-- <div class="file-rename">重命名</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="closeDialog">{{ $t('common.cancel') }}</el-button>
      <el-button type="primary" :loading="submitting" @click="onSubmit">{{ isEdit ? $t('common.save') :
        $t('common.submit')
        }}</el-button>
    </div>
  </el-dialog>
</template>

<script setup>
import dayjs from 'dayjs';
import {
  computed,
  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';

const props = defineProps({
  // 双向绑定的显示状态
  modelValue: { type: Boolean, default: false },
  // 'create' 快速提交；'edit' 编辑工单
  mode: { type: String, default: 'create' },
  // 仅在 edit 模式下使用：用于回填表单的工单详情数据
  orderData: { type: Object, default: () => ({}) },
  // 医院下拉数据源
  hospitals: { type: Array, default: () => [] },
  // 父组件控制的提交中 loading
  submitting: { type: Boolean, default: false },
});

const emit = defineEmits(['update:modelValue', 'submit', 'closed']);

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

const isEdit = computed(() => props.mode === 'edit');

// 颜色标签可选值
const colorOptions = [
  { label: '蓝', value: '#667eea' },
  { label: '绿', value: '#52c41a' },
  { label: '青', value: '#13c2c2' },
  { label: '紫', value: '#722ed1' },
  { label: '橙', value: '#fa8c16' },
  { label: '红', value: '#ff4d4f' },
];

// 优先级可选值（参考 ../list.vue 中的 priority-row 配色）
const priorityOptions = [
  { label: '高', value: '高', cls: 'high' },
  { label: '中', value: '中', cls: 'medium' },
  { label: '低', value: '低', cls: 'low' },
];

const colorPickerVisible = ref(false);
const selectColor = (val) => {
  form.colorTag = val;
  colorPickerVisible.value = false;
};

const formRef = ref();
// 弹窗打开到表单填充完毕这段时间的 loading（避免富文本在未挂载时被赋值）
const formLoading = ref(false);

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

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 中移除
  // - 新上传的文件(raw 存在)：仅前端移除，不会再被提交
  // - 编辑模式下的占位附件(无 raw)：从列表移除后，onSubmit 中不会再追加任何文件，从而保留后端的原附件行为
  form.files = (form.files || []).filter((f) => f.uid !== file?.uid);
};

const rules = {
  hospitalId: [
    {
      required: true,
      message: () => $t('msg.pleaseSelectHospital'),
      trigger: 'change',
    },
  ],
  title: [
    {
      required: true,
      message: () => $t('msg.pleaseInputTitle'),
      trigger: 'blur',
    },
  ],
  serviceType: [
    {
      required: true,
      message: () => $t('msg.pleaseSelectType'),
      trigger: 'blur',
    },
  ],
  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 editorRef = shallowRef();
const toolbarConfig = {
  excludeKeys: [
    'uploadImage',
    'insertVideo',
    'uploadVideo',
    'group-video',
    'emotion',
    'group-emoji',
  ],
};
const editorConfig = {
  placeholder: $t('placeholder.description'),
};

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

// 从剪贴板中捞出图片文件
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;
};

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 resetForm = () => {
  Object.assign(form, {
    hospitalId: undefined,
    title: '',
    serviceType: '',
    priority: '中',
    feedbackchannel: '',
    department: '',
    colorTag: '#667eea',
    description: '',
    submitter: '',
    createdat: '',
    files: [],
  });
  formRef.value?.clearValidate();
};

const fillFormFromOrder = (d) => {
  form.hospitalId =
    props.hospitals.find((h) => h.name === d.hospitalName)?.id || undefined;
  form.title = d.title || '';
  form.serviceType = d.serviceType || '';
  form.priority = d.priority || '中';
  form.feedbackchannel = d.feedbackChannel || d.feedbackchannel || '';
  form.department = d.department || '';
  form.colorTag = d.colorTag || '#667eea';
  form.description = d.description || '';
  form.submitter = d.submitter || '';
  // 后端返回时间可能含 T，统一格式化为 YYYY-MM-DD HH:mm:ss 供 date-picker 回显
  form.createdat = d.createdAt
    ? dayjs(d.createdAt).format('YYYY-MM-DD HH:mm:ss')
    : '';
  // 附件回显：把详情里的第一个附件作为 el-upload 的"已上传"项展示
  const atts = d.attachments || [];
  if (atts.length) {
    const first = atts[0];
    const fileName = first.fileName || getAttachmentFileName(first.filePath);
    if (fileName) {
      form.files = [
        {
          uid: `attachment-${d.id || ''}-0`,
          name: fileName,
          status: 'success',
          size: first.fileSize || 0,
        },
      ];
    }
  }
};

// 监听弹窗开启：重置 / 回填表单
watch(
  () => props.modelValue,
  (v) => {
    if (!v) return;
    formLoading.value = true;
    nextTick(() => {
      resetForm();
      // 有回显数据时(编辑模式 / 复制工单)优先按 orderData 填充
      if (isEdit.value || props.orderData) {
        fillFormFromOrder(props.orderData || {});
      } else {
        // 快速提交默认填入当前时间作为提交时间
        form.createdat = dayjs().format('YYYY-MM-DD HH:mm:ss');
      }
      formLoading.value = false;
    });
  },
);

const closeDialog = () => emit('update:modelValue', false);
const onClosed = () => {
  resetForm();
  emit('closed');
};

const onSubmit = async () => {
  // dept / submitter 去掉两端空格后再校验，避免仅含空格的"伪必填"绕过
  form.department = (form.department || '').trim();
  form.submitter = (form.submitter || '').trim();
  await formRef.value.validate(async (valid) => {
    if (!valid) return;
    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);
      }
    }
    // 仅在用户上传了真实文件时附带；编辑模式下的"已有附件"占位项没有 raw，不会被提交，
    // 从而保留后端的原附件（与原 detail.vue 的提交行为一致）
    for (const f of files || []) {
      if (f.raw) formData.append('files', f.raw, f.name);
    }
    emit('submit', { formData, mode: props.mode });
  });
};

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">
.admin-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);
  }

  // 标题 + 颜色标签 + 优先级 同一行
  .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;
  }

  .color-tag-preview {
    width: 24px;
    height: 24px;
    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;
  }

  // 优先级
  .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: #606266;
    font-weight: 400;
    font-size: 14px;
    color: #BCBCBC;
    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">
.admin-order-form-dialog {
  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-rename,
          .file-delete {
            color: #1D2129;

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

          .file-rename,
          .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;

  .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);
  }
}
</style>
