<template>
  <div class="page-wrap">
    <page-section :title="isCreate ? '新建 Bug' : '编辑 Bug'">
      <template slot="extra">
        <el-button size="small" @click="goBack">返回</el-button>
      </template>
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" size="small" class="bug-form">
        <el-form-item label="标题" prop="title">
          <el-input v-model.trim="form.title" maxlength="200" show-word-limit placeholder="Bug 标题" />
        </el-form-item>
        <el-row :gutter="16">
          <el-col :span="8">
            <el-form-item label="产品" prop="productId">
              <el-select v-model="form.productId" filterable placeholder="请选择产品" style="width: 100%;" @change="onProductChange" @focus="loadProductOptions">
                <el-option v-for="p in productOptions" :key="p.id" :label="p.name" :value="p.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="项目" prop="projectId">
              <el-select v-model="form.projectId" filterable placeholder="请选择项目" style="width: 100%;" :disabled="!form.productId" @change="onProjectChange">
                <el-option v-for="p in projectOptions" :key="p.id" :label="p.name" :value="p.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="模块" prop="moduleId">
              <el-select v-model="form.moduleId" filterable placeholder="请选择模块" style="width: 100%;" :disabled="!form.projectId">
                <el-option v-for="m in flatModules" :key="m.id" :label="m.name" :value="m.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="16">
          <el-col :span="8">
            <el-form-item label="类型" prop="bugType">
              <el-select v-model="form.bugType" placeholder="类型" style="width: 100%;">
                <el-option v-for="(label, key) in bugTypeOptions" :key="key" :label="label" :value="Number(key)" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="严重程度" prop="severity">
              <el-select v-model="form.severity" placeholder="严重程度" style="width: 100%;">
                <el-option v-for="(label, key) in severityOptions" :key="key" :label="label" :value="Number(key)" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="优先级" prop="priority">
              <el-select v-model="form.priority" placeholder="优先级" style="width: 100%;">
                <el-option v-for="(label, key) in priorityOptions" :key="key" :label="label" :value="Number(key)" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="16">
          <el-col :span="8">
            <el-form-item label="复现率" prop="reproduceRate">
              <el-select v-model="form.reproduceRate" placeholder="请选择复现率" style="width: 100%;">
                <el-option v-for="(label, key) in reproduceRateOptions" :key="key" :label="label" :value="Number(key)" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="16">
          <el-col v-if="!isCreate" :span="8">
            <el-form-item label="状态">
              <el-select v-model="form.status" clearable placeholder="状态" style="width: 100%;">
                <el-option v-for="(label, key) in statusOptions" :key="key" :label="label" :value="Number(key)" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="isCreate ? 12 : 8">
            <el-form-item label="创建人" prop="reporterId">
              <el-input
                v-if="isCreate"
                class="bug-creator-readonly"
                :value="defaultCreatorDisplayName"
                readonly
                placeholder="当前登录用户"
                style="width: 100%;" />
              <el-select
                v-else
                ref="reporterSelect"
                v-model="form.reporterId"
                filterable
                placeholder="请先选择项目"
                style="width: 100%;"
                popper-class="bug-editor-reporter-members"
                :disabled="!form.projectId"
                @visible-change="onReporterDropdownVisible">
                <el-option v-for="u in reporterMemberOptions" :key="'r-' + u.id" :label="u.name" :value="u.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="isCreate ? 12 : 8">
            <el-form-item label="当前指派" prop="assigneeId">
              <el-select
                ref="assigneeSelect"
                v-model="form.assigneeId"
                filterable
                placeholder="请选择当前指派"
                style="width: 100%;"
                popper-class="bug-editor-assignee-members"
                :disabled="!form.projectId"
                @visible-change="onAssigneeDropdownVisible">
                <el-option v-for="u in assigneeMemberOptions" :key="'a-' + u.id" :label="u.name" :value="u.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="16">
          <el-col :span="8">
            <el-form-item label="环境">
              <el-input v-model.trim="form.environment" maxlength="64" placeholder="如 st / pre" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="关联用例">
              <el-input v-model="form.caseId" placeholder="选填，用例 ID" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="关联计划">
              <el-input v-model="form.planId" placeholder="选填，计划 ID" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="复现步骤">
          <bug-steps-rich-editor :key="stepsEditorKey" v-model="form.steps" />
        </el-form-item>
        <el-form-item>
          <el-button @click="goBack">取消</el-button>
          <el-button type="primary" :loading="saving" @click="submit">{{ isCreate ? '创建' : '保存' }}</el-button>
        </el-form-item>
      </el-form>
    </page-section>
  </div>
</template>

<script>
import PageSection from '@/components/TestPlatform/common/PageSection'
import BugStepsRichEditor from '@/components/Bug/BugStepsRichEditor.vue'
import { getBugDetail, createBug, updateBug } from '@/api/bugApi'
import { recordBugHistory, recordBugEditDiff, buildBugEditBaseline } from '@/utils/bugHistory'
import { legacyStepsToEditorHtml, BUG_STEPS_DEFAULT_HTML } from '@/utils/bugStepsFormat'
import { getProductList } from '@/api/productApi'
import { getProjectList, getProjectMembers } from '@/api/projectApi'
import { getModuleTree } from '@/api/caseApi'
import { BUG_TYPE_MAP, SEVERITY_MAP, PRIORITY_MAP, STATUS_MAP, REPRODUCE_RATE_MAP } from '@/utils/bugMaps'

export default {
  name: 'BugEditor',
  components: { PageSection, BugStepsRichEditor },
  data() {
    return {
      saving: false,
      bugId: '',
      /** 新建页复制带入后递增，用于富文本编辑器 key 强制刷新 */
      editorNonce: 0,
      productOptions: [],
      projectOptions: [],
      moduleTree: [],
      memberPageSize: 10,
      reporterMemberOptions: [],
      reporterMemberPageNo: 0,
      reporterMemberNoMore: false,
      reporterMemberLoading: false,
      assigneeMemberOptions: [],
      assigneeMemberPageNo: 0,
      assigneeMemberNoMore: false,
      assigneeMemberLoading: false,
      assigneeExtraLabel: '',
      editBaseline: null,
      form: {
        title: '',
        bugType: 1,
        severity: 2,
        priority: 2,
        status: '',
        productId: '',
        projectId: '',
        moduleId: '',
        caseId: '',
        planId: '',
        environment: '',
        steps: BUG_STEPS_DEFAULT_HTML,
        reporterId: '',
        assigneeId: '',
        reproduceRate: 1
      },
      rules: {
        title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
        reproduceRate: [{ required: true, message: '请选择复现率', trigger: 'change' }],
        productId: [{ required: true, message: '请选择产品', trigger: 'change' }],
        projectId: [{ required: true, message: '请选择项目', trigger: 'change' }],
        moduleId: [{ required: true, message: '请选择模块', trigger: 'change' }],
        assigneeId: [{ required: true, message: '请选择当前指派', trigger: 'change' }],
        reporterId: [
          {
            required: true,
            validator: (rule, value, callback) => {
              if (this.isCreate) {
                const uid = this.defaultReporterId()
                if (uid === '' || uid === undefined || uid === null) {
                  callback(new Error('未获取到当前登录用户，请重新登录'))
                } else {
                  callback()
                }
                return
              }
              if (value === '' || value === undefined || value === null) {
                callback(new Error('请选择创建人'))
              } else {
                callback()
              }
            },
            trigger: 'change'
          }
        ]
      }
    }
  },
  computed: {
    isCreate() {
      return (this.$route.path || '').indexOf('/bug/create') !== -1
    },
    bugTypeOptions() {
      return BUG_TYPE_MAP
    },
    severityOptions() {
      return SEVERITY_MAP
    },
    priorityOptions() {
      return PRIORITY_MAP
    },
    statusOptions() {
      return STATUS_MAP
    },
    reproduceRateOptions() {
      return REPRODUCE_RATE_MAP
    },
    flatModules() {
      const out = []
      const walk = (nodes, prefix) => {
        ;(nodes || []).forEach(n => {
          const name = prefix ? `${prefix} / ${n.name}` : n.name
          out.push({ id: n.id, name })
          const ch = n.children || n.child_list || n.childList || []
          if (ch.length) walk(ch, name)
        })
      }
      walk(this.moduleTree, '')
      return out
    },
    stepsEditorKey() {
      if (this.isCreate) {
        return 'create-' + String(this.editorNonce)
      }
      return 'edit-' + String(this.bugId || '0')
    },
    currentUser() {
      return this.$store.state.currentUser
    },
    /** 新建页展示：优先 real_name（接口字段），与 store 中 realName 一致 */
    defaultCreatorDisplayName() {
      const u = this.currentUser
      if (!u) return '-'
      return u.real_name || u.realName || u.username || '-'
    }
  },
  watch: {
    '$route.query.bugId'(v) {
      this.bugId = v || ''
      if (!this.isCreate) this.loadDetail()
    },
    isCreate(val) {
      if (val) {
        if (this.$route.query.copyFrom) return
        this.form.steps = BUG_STEPS_DEFAULT_HTML
        this.form.reporterId = this.defaultReporterId()
        this.form.reproduceRate = 1
        this.form.assigneeId = ''
        this.assigneeExtraLabel = ''
        this.resetReporterMembers()
        this.resetAssigneeMembers()
      }
    },
    '$route.query.copyFrom': {
      handler(v) {
        if (!this.isCreate || !v) return
        this.loadProductOptions().then(() => this.applyCopyFromDetail(v))
      },
      immediate: true
    }
  },
  destroyed() {
    this.unbindReporterMemberScroll()
    this.unbindAssigneeMemberScroll()
  },
  methods: {
    defaultReporterId() {
      const u = this.currentUser
      return u && u.id != null && u.id !== '' ? u.id : ''
    },
    mapMemberRows(list) {
      const arr = Array.isArray(list) ? list : []
      return arr
        .map(item => ({
          id: item.user_id || item.userId || item.id,
          name:
            item.real_name ||
            item.realName ||
            item.username ||
            item.name ||
            item.user_name ||
            String(item.user_id || item.id)
        }))
        .filter(u => u.id !== undefined && u.id !== null)
    },
    ensureCurrentUserInMemberOptions(opts) {
      const u = this.currentUser
      if (!u || u.id == null || u.id === '') return opts || []
      const list = opts || []
      if (list.some(m => String(m.id) === String(u.id))) return list
      const label = u.realName || u.username || '当前用户'
      return [{ id: u.id, name: label }, ...list]
    },
    applyDefaultReporterIfNeeded() {
      if (!this.isCreate) return
      const uid = this.defaultReporterId()
      const inList = id =>
        id !== '' && id !== undefined && id !== null &&
        this.reporterMemberOptions.some(m => String(m.id) === String(id))
      if (!uid) return
      if (!this.form.reporterId || !inList(this.form.reporterId)) {
        if (inList(uid)) this.form.reporterId = uid
      }
    },
    mergeMemberById(existing, incoming) {
      const base = (existing || []).slice()
      const seen = new Set(base.map(x => String(x.id)))
      ;(incoming || []).forEach(x => {
        if (x.id === undefined || x.id === null) return
        const k = String(x.id)
        if (!seen.has(k)) {
          seen.add(k)
          base.push(x)
        }
      })
      return base
    },
    resetReporterMembers() {
      this.reporterMemberOptions = []
      this.reporterMemberPageNo = 0
      this.reporterMemberNoMore = false
    },
    resetAssigneeMembers() {
      this.assigneeMemberOptions = []
      this.assigneeMemberPageNo = 0
      this.assigneeMemberNoMore = false
    },
    fetchReporterMemberPage(append) {
      const pid = this.form.projectId
      if (!pid || this.reporterMemberLoading) return Promise.resolve()
      if (append && this.reporterMemberNoMore) return Promise.resolve()
      const nextPage = append ? this.reporterMemberPageNo + 1 : 1
      if (!append) {
        this.resetReporterMembers()
      }
      this.reporterMemberLoading = true
      return getProjectMembers(pid, { pageNo: nextPage, pageSize: this.memberPageSize })
        .then(res => {
          const data = (res && res.data) || res || {}
          const raw = data.items || data.list || data.data || []
          const rows = this.mapMemberRows(Array.isArray(raw) ? raw : [])
          if (append) {
            this.reporterMemberOptions = this.mergeMemberById(this.reporterMemberOptions, rows)
          } else {
            this.reporterMemberOptions = this.ensureCurrentUserInMemberOptions(rows)
          }
          this.reporterMemberPageNo = nextPage
          this.reporterMemberNoMore = rows.length < this.memberPageSize
        })
        .catch(() => {
          if (!append) {
            this.reporterMemberOptions = this.ensureCurrentUserInMemberOptions([])
          }
          this.reporterMemberNoMore = true
        })
        .finally(() => {
          this.reporterMemberLoading = false
        })
        .then(() => {
          this.applyDefaultReporterIfNeeded()
        })
    },
    fetchAssigneeMemberPage(append) {
      const pid = this.form.projectId
      if (!pid || this.assigneeMemberLoading) return Promise.resolve()
      if (append && this.assigneeMemberNoMore) return Promise.resolve()
      const nextPage = append ? this.assigneeMemberPageNo + 1 : 1
      if (!append) {
        this.resetAssigneeMembers()
      }
      this.assigneeMemberLoading = true
      return getProjectMembers(pid, { pageNo: nextPage, pageSize: this.memberPageSize })
        .then(res => {
          const data = (res && res.data) || res || {}
          const raw = data.items || data.list || data.data || []
          const rows = this.mapMemberRows(Array.isArray(raw) ? raw : [])
          if (append) {
            this.assigneeMemberOptions = this.mergeMemberById(this.assigneeMemberOptions, rows)
          } else {
            this.assigneeMemberOptions = rows.slice()
          }
          this.assigneeMemberPageNo = nextPage
          this.assigneeMemberNoMore = rows.length < this.memberPageSize
          this.ensureAssigneeInOptions()
        })
        .catch(() => {
          if (!append) this.assigneeMemberOptions = []
          this.assigneeMemberNoMore = true
        })
        .finally(() => {
          this.assigneeMemberLoading = false
        })
    },
    ensureAssigneeInOptions() {
      const id = this.form.assigneeId
      if (id === '' || id === undefined || id === null) return
      if (this.assigneeMemberOptions.some(m => String(m.id) === String(id))) return
      const name = this.assigneeExtraLabel || `用户 ${id}`
      this.assigneeMemberOptions = [{ id, name }, ...this.assigneeMemberOptions]
    },
    getMemberDropdownScrollWrap(popperClass) {
      const pop = document.querySelector(`.${popperClass}`)
      if (!pop) return null
      return pop.querySelector('.el-select-dropdown__wrap') || pop.querySelector('.el-scrollbar__wrap')
    },
    unbindReporterMemberScroll() {
      if (this._reporterScrollEl && this._reporterScrollHandler) {
        this._reporterScrollEl.removeEventListener('scroll', this._reporterScrollHandler)
      }
      this._reporterScrollEl = null
      this._reporterScrollHandler = null
    },
    unbindAssigneeMemberScroll() {
      if (this._assigneeScrollEl && this._assigneeScrollHandler) {
        this._assigneeScrollEl.removeEventListener('scroll', this._assigneeScrollHandler)
      }
      this._assigneeScrollEl = null
      this._assigneeScrollHandler = null
    },
    bindReporterMemberScroll() {
      this.unbindReporterMemberScroll()
      this.$nextTick(() => {
        const el = this.getMemberDropdownScrollWrap('bug-editor-reporter-members')
        if (!el) return
        this._reporterScrollEl = el
        this._reporterScrollHandler = this.onReporterMemberDropdownScroll.bind(this)
        el.addEventListener('scroll', this._reporterScrollHandler, { passive: true })
      })
    },
    bindAssigneeMemberScroll() {
      this.unbindAssigneeMemberScroll()
      this.$nextTick(() => {
        const el = this.getMemberDropdownScrollWrap('bug-editor-assignee-members')
        if (!el) return
        this._assigneeScrollEl = el
        this._assigneeScrollHandler = this.onAssigneeMemberDropdownScroll.bind(this)
        el.addEventListener('scroll', this._assigneeScrollHandler, { passive: true })
      })
    },
    onReporterMemberDropdownScroll(e) {
      const el = e.target
      if (this.reporterMemberLoading || this.reporterMemberNoMore) return
      if (el.scrollHeight - el.scrollTop - el.clientHeight < 40) {
        this.fetchReporterMemberPage(true)
      }
    },
    onAssigneeMemberDropdownScroll(e) {
      const el = e.target
      if (this.assigneeMemberLoading || this.assigneeMemberNoMore) return
      if (el.scrollHeight - el.scrollTop - el.clientHeight < 40) {
        this.fetchAssigneeMemberPage(true)
      }
    },
    onReporterDropdownVisible(visible) {
      if (!visible) {
        this.unbindReporterMemberScroll()
        return
      }
      if (!this.form.projectId) return
      const load = !this.reporterMemberOptions.length
        ? this.fetchReporterMemberPage(false)
        : Promise.resolve()
      load.finally(() => {
        this.$nextTick(() => this.bindReporterMemberScroll())
      })
    },
    onAssigneeDropdownVisible(visible) {
      if (!visible) {
        this.unbindAssigneeMemberScroll()
        return
      }
      if (!this.form.projectId) return
      const load = !this.assigneeMemberOptions.length
        ? this.fetchAssigneeMemberPage(false)
        : Promise.resolve()
      load.finally(() => {
        this.$nextTick(() => this.bindAssigneeMemberScroll())
      })
    },
    loadProjectMembersForForm(projectId) {
      if (!projectId) {
        this.resetReporterMembers()
        this.resetAssigneeMembers()
        return Promise.resolve()
      }
      if (this.isCreate) {
        this.resetReporterMembers()
        return this.fetchAssigneeMemberPage(false)
      }
      return Promise.all([
        this.fetchReporterMemberPage(false),
        this.fetchAssigneeMemberPage(false)
      ])
    },
    loadProductOptions() {
      if (this.productOptions.length) return Promise.resolve()
      return getProductList({ pageNo: 1, pageSize: 1000, status: 1 }).then(res => {
        const data = (res && res.data) || res || {}
        this.productOptions = data.items || data.list || data.data || []
      }).catch(() => { this.productOptions = [] })
    },
    loadProjects(productId) {
      if (!productId) {
        this.projectOptions = []
        return Promise.resolve()
      }
      return getProjectList({ pageNo: 1, pageSize: 1000, status: 1, productId }).then(res => {
        const data = (res && res.data) || res || {}
        this.projectOptions = data.items || data.list || data.data || []
      }).catch(() => { this.projectOptions = [] })
    },
    loadModules(projectId) {
      if (!projectId) {
        this.moduleTree = []
        return Promise.resolve()
      }
      return getModuleTree({ projectId, pageNo: 1, pageSize: 1000 }).then(res => {
        const data = (res && res.data) || res || {}
        this.moduleTree = data.list || data.items || []
      }).catch(() => { this.moduleTree = [] })
    },
    onProductChange(val) {
      this.form.projectId = ''
      this.form.moduleId = ''
      this.form.assigneeId = ''
      this.form.reporterId = this.defaultReporterId()
      this.moduleTree = []
      this.assigneeExtraLabel = ''
      this.resetReporterMembers()
      this.resetAssigneeMembers()
      this.loadProjects(val)
    },
    onProjectChange(val) {
      this.form.moduleId = ''
      this.form.assigneeId = ''
      this.assigneeExtraLabel = ''
      this.loadModules(val)
      this.loadProjectMembersForForm(val)
    },
    applyCopyTitle(raw) {
      const t = String(raw || '').trim()
      const suffix = '（复制）'
      if (!t) return suffix
      if (t.indexOf(suffix) !== -1) {
        return t.length > 200 ? t.slice(0, 200) : t
      }
      const combined = t + suffix
      if (combined.length <= 200) return combined
      return t.slice(0, Math.max(0, 200 - suffix.length)) + suffix
    },
    applyCopyFromDetail(sourceBugId) {
      const sid = String(sourceBugId || '').trim()
      if (!sid) return Promise.resolve()
      return getBugDetail(sid)
        .then(res => {
          const d = (res && res.data) || res || {}
          this.assigneeExtraLabel =
            d.assignee_real_name ||
            d.assigneeRealName ||
            d.assignee_name ||
            d.assigneeName ||
            d.assignee_username ||
            d.assigneeUsername ||
            ''
          const rawSteps =
            d.steps || d.reproduce_steps || d.reproduceSteps || d.reproduction_steps || d.reproductionSteps || ''
          this.form = {
            title: this.applyCopyTitle(d.title || ''),
            bugType: d.bug_type != null ? d.bug_type : d.bugType != null ? d.bugType : 1,
            severity: d.severity != null ? d.severity : 2,
            priority: d.priority != null ? d.priority : 2,
            status: '',
            productId: d.product_id || d.productId || '',
            projectId: d.project_id || d.projectId || '',
            moduleId: d.module_id || d.moduleId || '',
            caseId: d.case_id != null && d.case_id !== '' ? d.case_id : d.caseId != null && d.caseId !== '' ? d.caseId : '',
            planId: d.plan_id != null && d.plan_id !== '' ? d.plan_id : d.planId != null && d.planId !== '' ? d.planId : '',
            environment: d.environment || '',
            steps: legacyStepsToEditorHtml(rawSteps),
            reporterId: this.defaultReporterId(),
            assigneeId: d.assignee_id || d.assigneeId || '',
            reproduceRate:
              d.reproduce_rate != null && d.reproduce_rate !== ''
                ? Number(d.reproduce_rate)
                : d.reproduceRate != null && d.reproduceRate !== ''
                  ? Number(d.reproduceRate)
                  : 1
          }
          if (this.form.productId) this.loadProjects(this.form.productId)
          if (this.form.projectId) {
            this.loadModules(this.form.projectId)
            this.loadProjectMembersForForm(this.form.projectId)
          }
          this.editorNonce = (this.editorNonce || 0) + 1
          this.bugId = ''
          this.editBaseline = null
          this.$nextTick(() => {
            if (this.$refs.formRef) this.$refs.formRef.clearValidate()
          })
          this.$message.success('已带入原 Bug 内容，请确认后创建')
        })
        .then(() => this.$router.replace({ path: '/bug/create', query: {} }).catch(() => {}))
        .catch(() => {
          this.$message.error('复制失败：无法加载原 Bug 详情')
        })
    },
    loadDetail() {
      if (!this.bugId) return
      getBugDetail(this.bugId).then(res => {
        const d = (res && res.data) || res || {}
        this.assigneeExtraLabel =
          d.assignee_real_name ||
          d.assigneeRealName ||
          d.assignee_name ||
          d.assigneeName ||
          d.assignee_username ||
          d.assigneeUsername ||
          ''
        const rawSteps =
          d.steps || d.reproduce_steps || d.reproduceSteps || d.reproduction_steps || d.reproductionSteps || ''
        this.form = {
          title: d.title || '',
          bugType: d.bug_type != null ? d.bug_type : (d.bugType != null ? d.bugType : 1),
          severity: d.severity != null ? d.severity : 2,
          priority: d.priority != null ? d.priority : 2,
          status: d.status != null ? d.status : '',
          productId: d.product_id || d.productId || '',
          projectId: d.project_id || d.projectId || '',
          moduleId: d.module_id || d.moduleId || '',
          caseId: d.case_id || d.caseId || '',
          planId: d.plan_id || d.planId || '',
          environment: d.environment || '',
          steps: legacyStepsToEditorHtml(rawSteps),
          reporterId:
            d.reporter_id ||
            d.reporterId ||
            d.creator_id ||
            d.creatorId ||
            d.created_by ||
            d.createdBy ||
            '',
          assigneeId: d.assignee_id || d.assigneeId || '',
          reproduceRate:
            d.reproduce_rate != null && d.reproduce_rate !== ''
              ? Number(d.reproduce_rate)
              : d.reproduceRate != null && d.reproduceRate !== ''
                ? Number(d.reproduceRate)
                : 1
        }
        if (this.form.productId) this.loadProjects(this.form.productId)
        if (this.form.projectId) {
          this.loadModules(this.form.projectId)
          this.loadProjectMembersForForm(this.form.projectId)
        }
        this.$nextTick(() => {
          this.editBaseline = buildBugEditBaseline(this.form)
        })
      }).catch(() => {})
    },
    clean(obj) {
      const o = {}
      Object.keys(obj).forEach(k => {
        const v = obj[k]
        if (v !== '' && v !== undefined && v !== null) o[k] = v
      })
      return o
    },
    submit() {
      this.$refs.formRef.validate(valid => {
        if (!valid) return
        this.saving = true
        if (this.isCreate) {
          const payload = this.clean({
            title: this.form.title,
            bugType: this.form.bugType,
            severity: this.form.severity,
            priority: this.form.priority,
            productId: this.form.productId,
            projectId: this.form.projectId,
            moduleId: this.form.moduleId,
            caseId: this.form.caseId,
            planId: this.form.planId,
            environment: this.form.environment,
            steps: this.form.steps,
            reporterId: this.form.reporterId,
            assigneeId: this.form.assigneeId,
            reproduceRate: this.form.reproduceRate
          })
          payload.description = ''
          createBug(payload).then(res => {
            const data = (res && res.data) || {}
            this.$message.success('创建成功')
            const id = data.id
            if (id) {
              recordBugHistory(this.$store, {
                bugId: id,
                fieldName: 'create',
                oldValue: '',
                newValue: '1'
              })
              this.$router.replace({ path: '/bug/detail', query: { bugId: id } })
            } else {
              this.$router.push({ path: '/bug/list' })
            }
          }).finally(() => { this.saving = false })
        } else {
          const payload = this.clean({
            bugId: Number(this.bugId),
            id: Number(this.bugId),
            title: this.form.title,
            bugType: this.form.bugType,
            severity: this.form.severity,
            priority: this.form.priority,
            status: this.form.status,
            reporterId: this.form.reporterId,
            assigneeId: this.form.assigneeId,
            moduleId: this.form.moduleId,
            caseId: this.form.caseId,
            planId: this.form.planId,
            environment: this.form.environment,
            steps: this.form.steps,
            reproduceRate: this.form.reproduceRate
          })
          payload.description = ''
          updateBug(payload)
            .then(() =>
              recordBugEditDiff(
                this.$store,
                Number(this.bugId),
                this.editBaseline,
                buildBugEditBaseline(this.form)
              )
            )
            .then(() => {
              this.$message.success('保存成功')
              this.$router.push({ path: '/bug/detail', query: { bugId: this.bugId } })
            })
            .finally(() => {
              this.saving = false
            })
        }
      })
    },
    goBack() {
      if (this.isCreate) {
        this.$router.push({ path: '/bug/list' })
      } else {
        this.$router.push({ path: '/bug/detail', query: { bugId: this.bugId } })
      }
    }
  },
  created() {
    this.bugId = this.$route.query.bugId || ''
    if (this.isCreate) {
      this.form.reporterId = this.defaultReporterId()
    }
    if (!this.isCreate) {
      this.loadProductOptions().then(() => this.loadDetail())
    } else if (!this.$route.query.copyFrom) {
      this.loadProductOptions()
    }
  }
}
</script>

<style scoped>
.page-wrap {
  padding: 20px;
}
.bug-form {
  max-width: 960px;
}

.bug-creator-readonly >>> .el-input__inner {
  cursor: default;
  color: #606266;
  background-color: #f5f7fa;
}
</style>
