<template>
  <wrapper
    v-loading="!dataMap.length"
    fill
    margin
    padding
    background
  >
    <status-wrapper
      slot="empty"
      :error="error"
      @click="getPublishWorkflowDetail"
    />
    <template v-if="dataMap.length">
      <div class="l-flex--row o-title has-bottom-padding u-color--black u-bold">{{ title }} <span class="applicant">{{ createBy?`申请人：${createBy}`:'' }}</span></div>
      <div class="l-flex--row has-padding">
        <el-steps
          :active="active"
          finish-status="success"
          class="l-flex__fill"
          align-center
        >
          <el-step
            v-if="dataMap.includes('minios')"
            title="媒资审核"
          />
          <el-step
            v-if="dataMap.includes('items')"
            title="节目审核"
          />
          <el-step
            v-if="dataMap.includes('carousels')"
            title="轮播审核"
          />
          <el-step
            v-if="dataMap.includes('programCalendar')"
            title="排期审核"
          />
          <el-step
            v-if="dataMap.includes('calendarReleaseScheduling')"
            title="发布审核"
          />
          <el-step title="完成" />
        </el-steps>
      </div>

      <div class="l-flex--row fl-end has-padding">
        <!-- <el-button
          v-if="active === totalStep - 2"
          class="o-button"
          @click="onPublish"
          >确认发布</el-button
        > -->
        <el-button
          v-if="showTempReject && tempRejectInfo.length"
          class="o-button"
          @click="reject()"
        >{{ tempRejectMap[backDataType]["text"] }}</el-button>
      </div>
      <schema-table
        v-if="active < totalStep"
        ref="table"
        :key="tableKey"
        :schema="schema"
        @row-click="onToggle"
      >
        <preview-dialog ref="previewDialog" />
        <review-dialog
          v-if="dataMap[active] === 'minios'"
          ref="reviewDialog"
          :list="tableData"
          @resolve="onResolve"
          @reject="onConfirmReject"
        />
        <program-dialog ref="programDialog" />
        <schedule-dialog ref="scheduleDialog" />
      </schema-table>
      <div
        v-if="active === totalStep"
        class="o-card has-padding"
      >
        <i class="el-icon-success o-card__icon" />
        <div class="o-card__title">发布成功</div>
        <div class="o-card__desc">排期发布成功！</div>
      </div>
      <confirm-dialog
        ref="rejectDialog"
        title="驳回"
        @confirm="onConfirmReject"
      >
        <div class="c-grid-form u-align-self--center">
          <span class="c-grid-form__label">审核意见：</span>
          <el-select
            v-model="review.type"
            placeholder="请选择"
          >
            <el-option
              v-for="option in reviewOptions"
              :key="option.label"
              :label="option.label"
              :value="option.value"
            />
          </el-select>
          <template v-if="review.type === 'reject'">
            <span class="c-grid-form__label required">原因：</span>
            <el-input
              v-model.trim="review.reason"
              type="textarea"
              placeholder="请填写驳回原因"
              maxlength="50"
              :rows="3"
              resize="none"
              show-word-limit
            />
          </template>
        </div>
      </confirm-dialog>
    </template>
  </wrapper>
</template>

<script>
import ReviewDialog from './components/ReviewDialog'
import {
  getPublishWorkflowDetail,
  calendarPublishReject
} from '@/api/workflow'
import { resolveAsset } from '@/api/asset'
import { resolveProgram } from '@/api/program'
import { resolveSchedule } from '@/api/calendar'
import { resolvePublish } from '@/api/platform'
import {
  parseByte, parseDuration
} from '@/utils'
import mediaMixin from '@/views/platform/media/mixin.js'
import {
  State,
  EventPriority,
  EventFreq,
  EventTarget,
  PublishType,
  AssetType
} from '@/constant'
// 前端命名 和后端数据命名
const front2back = {
  assets: 'minios',
  program: 'items',
  programRecur: 'carousels',
  schedule: 'programCalendar',
  publish: 'calendarReleaseScheduling'
}
// 数据 是否单个还是list
const singleMap = {
  minios: false,
  items: false,
  carousels: false,
  programCalendar: true,
  calendarReleaseScheduling: true
}
// 数据 转 驳回type
const data2type = {
  minios: 'minio',
  items: 'item',
  carousels: 'carousel',
  programCalendar: 'program',
  calendarReleaseScheduling: 'calendar'
}
// label
const data2label = {
  minios: '媒资',
  items: '节目',
  carousels: '轮播',
  programCalendar: '排期',
  calendarReleaseScheduling: '发布'
}
function showOpt (status) {
  return ![State.RESOLVED, State.REJECTED].includes(status)
}
const allDataMap = [
  'minios',
  'items',
  'carousels',
  'programCalendar',
  'calendarReleaseScheduling'
]

export default {
  name: 'ReviewDetail',
  components: {
    ReviewDialog
  },
  data () {
    return {
      error: false,
      dataMap: [],
      active: 0,
      tableKey: 1,
      sourceMap: {}, // 总数据
      loaded: false,
      reviewOptions: [
        { value: 'reject', label: '驳回' },
        { value: '图文不符' },
        { value: '内容不合规' }
      ],
      review: {
        type: '',
        reason: ''
      },
      tempRejectInfo: [],
      tempRejectMap: {}
    }
  },
  computed: {
    backDataType () {
      return this.dataMap[this.active]
    },
    tableData () {
      return this.sourceMap[this.backDataType] || []
    },
    id () {
      return this.$route.params.id
    },
    title () {
      return this.$route.params.name
    },
    createBy () {
      return this.$route.params.createBy
    },
    totalStep () {
      return this.dataMap.length + 1
    },
    showTempReject () {
      if (
        this.tempRejectMap[this.backDataType]
        && this.tempRejectMap[this.backDataType].length > 1
      ) {
        return true
      }
      return false
    },
    schema () {
      switch (this.backDataType) {
        case front2back.assets:
          return {
            list: this.getList('assets'),
            cols: [
              { prop: 'typeName', label: '类型', align: 'center', width: 80 },
              { prop: 'file', type: 'asset', on: this.onViewAsset },
              { prop: 'originalName', label: '' },
              { prop: 'duration', label: '时长' },
              { prop: 'size', label: '文件大小' },
              // { prop: 'createBy', label: '申请人' },
              { prop: 'ai', label: 'AI审核', type: 'tag', width: 100 },
              {
                label: '审核状态',
                type: 'tag',
                render ({ status }) {
                  return {
                    type: ['warning', 'warning', 'success', 'danger'][status],
                    label: ['未审核', '未审核', '通过', '驳回'][status]
                  }
                }
              },
              {
                type: 'invoke',
                width: 80,
                render: [{ label: '审核', on: this.onView, render ({ status }) {
                  return showOpt(status)
                } }]
              }
            ]
          }
        case front2back.program:
          return {
            list: this.getList('program'),
            cols: [
              { prop: 'name', label: '节目名称', 'min-width': 100 },
              { prop: 'resolutionRatio', label: '分辨率' },
              // { prop: 'createBy', label: '申请人' },
              {
                label: '审核状态',
                type: 'tag',
                render ({ status }) {
                  return {
                    type: ['warning', 'warning', 'success', 'danger'][status],
                    label: ['未审核', '未审核', '通过', '驳回'][status]
                  }
                }
              },
              {
                type: 'invoke',
                width: 160,
                render: [
                  { label: '查看', on: this.onView },
                  {
                    label: '通过',
                    render ({ status }) {
                      return showOpt(status)
                    },
                    on: this.onResolve
                  },
                  {
                    label: '驳回',
                    render ({ status }) {
                      return showOpt(status)
                    },
                    on: this.onReject
                  }
                ]
              }
            ]
          }
        case front2back.programRecur:
        case front2back.schedule:
          return {
            list: this.getList('schedule'),
            cols: [
              { prop: 'name', label: '排期名称', 'min-width': 100 },
              { prop: 'resolutionRatio', label: '分辨率' },
              // { prop: 'createBy', label: '申请人' },
              {
                label: '审核状态',
                type: 'tag',
                render ({ status }) {
                  return {
                    type: ['warning', 'warning', 'success', 'danger'][status],
                    label: ['未审核', '未审核', '通过', '驳回'][status]
                  }
                }
              },
              {
                type: 'invoke',
                width: 160,
                render: [
                  { label: '查看', on: this.onView },
                  {
                    label: '通过',
                    render ({ status }) {
                      return showOpt(status)
                    },
                    on: this.onResolve
                  },
                  {
                    label: '驳回',
                    render ({ status }) {
                      return showOpt(status)
                    },
                    on: this.onReject
                  }
                ]
              }
            ]
          }
        case front2back.publish:
          return {
            list: this.getList('publish'),
            cols: [
              {
                prop: 'expand',
                type: 'expand',
                render (data, h) {
                  return h(
                    'div',
                    {
                      staticClass: 'o-info'
                    },
                    [
                      h('div', null, data.desc),
                      h('div', null, `设备：${data.device}`)
                    ]
                  )
                }
              },
              { prop: 'type', label: '类型', width: 100 },
              { prop: 'name', label: '名称', 'min-width': 100 },
              { prop: 'resolutionRatio', label: '分辨率' },
              {
                type: 'invoke',
                width: 160,
                render: [
                  { label: '查看', on: this.onView },
                  {
                    label: '通过',
                    render ({ status }) {
                      return showOpt(status)
                    },
                    on: this.onPublish
                  },
                  {
                    label: '驳回',
                    render ({ status }) {
                      return showOpt(status)
                    },
                    on: this.onReject
                  }
                ]
              }
            ]
          }
        default:
          return {}
      }
    }
  },
  mounted () {
    this.getPublishWorkflowDetail()
  },
  methods: {
    // 判断是否需要缓存驳回
    calTempReject (item) {
      if (!singleMap[item]) {
        this.tempRejectMap[item] = {
          text: `${data2label[item]}驳回`,
          show:
            !this.tempRejectMap.length
            && this.sourceMap[item].filter(i => ![State.RESOLVED, State.REJECTED].includes(i.status))
              .length
        }
      }
    },
    async getPublishWorkflowDetail () {
      let res = await getPublishWorkflowDetail(this.id).catch(err => {
        console.log(err)
      })
      if (!res || !res.success) {
        this.error = true
        return
      }
      this.error = false
      res = res.data
      for (const key in res) {
        if (Object.prototype.hasOwnProperty.call(res, key)) {
          const element = res[key]
          if (!Array.isArray(element)) {
            res[key] = [element]
          }
        }
      }

      this.sourceMap = res
      // init
      // 判断步骤 filter datamap 并transform row
      const temp = []
      for (const item of allDataMap) {
        if (this.sourceMap[item][0]) {
          this.sourceMap[item] = this.sourceMap[item].map(row => this.transform(row, item))
          temp.push(item)
          // 处理缓存驳回初始状态
          if (!singleMap[item]) {
            this.tempRejectMap[item] = {
              text: `${data2label[item]}驳回`,
              length: this.sourceMap[item].filter(
                i => ![State.RESOLVED, State.REJECTED].includes(i.status)
              ).length
            }
          }
        }
      }
      this.dataMap = temp
      // 确定节点
      let active = 0
      for (const item of this.dataMap) {
        if (this.sourceMap[item].every(i => i.status === State.RESOLVED)) {
          active++
          continue
        }
        break
      }
      this.active = active
      if (this.active === this.totalStep - 1) {
        this.active = this.totalStep
      }
    },
    refresh () {
      this.getPublishWorkflowDetail()
    },
    refreshStatus (item, status, review) {
      const list = this.tableData
      const index = list.findIndex(i => i.id === item.id)
      list[index].status = status
      this.$refs.table.onPagination()
      if (status === State.RESOLVED && this.tableData.every(i => i.status === State.RESOLVED)) {
        this.closePreviewDialog()
        this.nextStep()
      }
      if (status === State.REJECTED) {
        list[index].review = review
      }
    },
    getList () {
      return () => Promise.resolve({ data: this.tableData, totalCount: 1 })
    },
    // 全部审批通过
    nextStep () {
      this.active += 1
      if (this.active === this.totalStep - 1) {
        this.active = this.totalStep
      }
      this.tempRejectInfo = []
      this.tableKey++
    },
    next () {
      if (this.active++ > 5) {
        this.active = 0
      }
      this.tableKey++
    },
    transform (row, kind) {
      const { type } = row
      switch (kind) {
        case front2back['assets']:
          if (row.type === AssetType.IMAGE) {
            row.thumbnail = row.keyName
          } else if (row.type === AssetType.VIDEO && row.screenshot !== 'analyzing') {
            row.thumbnail = row.screenshot
          }
          row.typeName = [null, '图片', '视频', '音频'][type]
          row.file = {
            type: row.type,
            url: row.keyName,
            thumbnail: row.thumbnail
          }
          row.duration = parseDuration(row.duration)
          row.size = parseByte(row.size)
          row.createBy = row.userName || row.createBy
          row.ai = mediaMixin.methods.getAIState(row)
          row.aiLabel = row.ai.label
          row.id = row.keyName
          return row
        case front2back['program']:
          row.createBy = row.userName || row.createBy
          return row
        case front2back['publish']:
          return { ...this.getSame(row), ...this.getDiff(row) }
        default:
          return row
      }
    },
    // publish 排期辅助函数
    getSame ({
      id,
      programCalendarName,
      resolutionRatio,
      createBy,
      createByUsername,
      createTime,
      calendarReleaseDeviceList
    }) {
      return {
        id,
        name: programCalendarName,
        resolutionRatio,
        createBy: createByUsername || createBy,
        createTime,
        device: calendarReleaseDeviceList
          ?.map(item => item.deviceName)
          .join('，')
      }
    },
    getDiff (item) {
      const target = JSON.parse(item.target)
      let type = ''
      switch (target.type) {
        case PublishType.CALENDAR:
          type = '排期'
          break
        case PublishType.EVENT:
          type = ['', '默认播放', '单播', '插播'][target.detail.priority]
          break
        default:
          break
      }
      return {
        type,
        target,
        desc: this.getDesc(target)
      }
    },
    getDesc (target) {
      if (
        target.type === PublishType.EVENT
        && target.detail.priority === EventPriority.INSERTED
      ) {
        const { freq, start, until, byDay, startTime, endTime } = target.detail
        switch (freq) {
          case EventFreq.WEEKLY:
            return `自${start.split(' ')[0]}开始${
              until ? `${until.split(' ')[0]}前` : ''
            } 每周${byDay
              .split(',')
              .map(val => ['日', '一', '二', '三', '四', '五', '六'][val])
              .join('、')} ${startTime} - ${endTime}`
          default:
            return until ? `${start} - ${until}` : `自${start}开始`
        }
      }
      return ''
    },
    onToggle (row) {
      if (this.backDataType !== front2back.publish) {
        return
      }
      this.$refs.table.getInst().toggleRowExpansion(row)
    },
    onPublishView ({ target: { type, detail } }) {
      switch (type) {
        case PublishType.CALENDAR:
          this.viewSchedule(detail)
          break
        case PublishType.EVENT:
          if (detail.target.type === EventTarget.RECUR) {
            this.viewSchedule(detail.target.id)
          } else {
            this.viewProgram(detail.target.id)
          }
          break
        default:
          break
      }
    },
    viewSchedule (id) {
      this.$refs.scheduleDialog.show(id)
    },
    viewProgram (id) {
      this.$refs.programDialog.show(id)
    },
    // 查看
    onView (row) {
      const { id } = row
      switch (this.backDataType) {
        case front2back.assets:
          this.$refs.reviewDialog.show(
            this.tableData.findIndex(i => i.id === id)
          )
          break
        case front2back.program:
          this.viewProgram(id)
          break
        case front2back.schedule:
        case front2back.programRecur:
          this.viewSchedule(id)
          break
        case front2back.publish:
          this.onPublishView(row)
          break
        default:
          break
      }
    },
    onViewAsset (asset) {
      this.$refs.previewDialog.show(asset)
    },
    closePreviewDialog () {
      if (this.backDataType === front2back.assets) {
        this.$refs.reviewDialog.close()
      }
    },
    // 通过
    onResolve (item, done) {
      this.resolve(item).then(() => {
        this.refreshStatus(item, State.RESOLVED)
        done && done()
      })
    },
    resolve (item) {
      switch (this.backDataType) {
        case front2back.assets:
          return resolveAsset(item)
        case front2back.program:
          return resolveProgram(item)
        case front2back.schedule:
        case front2back.programRecur:
          return resolveSchedule(item)
        case front2back.publish:
          return resolvePublish(item)
        default:
          return new Promise().reject()
      }
    },
    // 行内
    // 驳回 列表按钮触发
    onReject (item) {
      this.$item = item
      this.review = {
        type: 'reject',
        reason: ''
      }
      this.$refs.rejectDialog.show()
    },
    // dialog 直接触发
    onConfirmReject (done, props) {
      if (props) {
        const { item, review } = props
        this.$item = item
        this.review = review
      }
      const reason =
        this.review.type === 'reject' ? this.review.reason : this.review.type
      if (!reason) {
        this.$message({
          type: 'warning',
          message: '请选择或填写驳回原因'
        })
        return
      }
      const rejectInfo = {
        id: this.$item.id,
        name: this.$item.name || this.$item.originalName,
        remark: reason
      }
      if (this.showTempReject) {
        this.$confirm(`驳回 ${rejectInfo.name} ？`, {
          type: 'warning'
        }).then(() => {
          // 缓存驳回数据
          done()
          this.tempRejectInfo.push(rejectInfo)
          this.refreshStatus(this.$item, State.REJECTED, {
            type: this.review.type,
            reason: this.review.reason
          })
          // 自动触发媒资驳回的二次确认弹窗
          if (!this.tableData.filter(i => ![State.RESOLVED, State.REJECTED].includes(i.status)).length) {
            this.reject()
          }
        })
      } else {
        // 单数据方取最新 直接驳回接口 单数据方法不回调，确认验证在接口方法
        this.reject([rejectInfo], rejectInfo.name)
      }
    },
    // 流程驳回
    reject (
      rejectInfo = this.tempRejectInfo,
      name = data2label[this.backDataType]
    ) {
      return calendarPublishReject(
        this.id,
        {
          type: data2type[this.backDataType],
          rejectInfo
        },
        name
      )
        .then(() => {
          this.$router.push({ name: 'workflow-list' })
        })
        .catch(err => {
          console.log(err)
        })
    },

    // 确认发布
    onPublish () {
      resolvePublish({
        name: this.tableData[0].programCalendarName,
        id: this.tableData[0].id
      }).then(() => {
        this.nextStep()
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.o-card {
  display: flex;
  align-items: center;
  flex-direction: column;
  width: 100%;
  padding-top: 100px;
  &__icon {
    color: #04a681;
    font-size: 48px;
  }
  &__title {
    font-size: 16px;
    font-weight: 500;
    color: #333333;
    line-height: 36px;
  }
  &__desc {
    font-weight: 400;
    color: #d5d9e4;
    line-height: 36px;
    font-size: 14px;
    padding-left: 15px;
  }
}
.o-title {
  font-size: 18px;
}
.fl-end {
  justify-content: flex-end;
}
.applicant {
  font-size: 14px;
  margin-left: 30px;
  font-weight: 400;
}
</style>
