<template>
  <div>
    <!-- title="选择景点检票" -->
    <el-dialog
      :title="titleOfScenicDlg"
      :visible.sync="refundScenicDlgVisible"
    >
      <el-form
        :inline="true"
        style="padding:20px;"
        label-width="70px">
        <el-form-item
          label="景点选择"
        >
          <el-select
            v-model="selectedRefundScenicId"
            placeholder="请选择景点">
            <el-option
              v-for="item in refundScenicArr"
              :key="item.id"
              :value="item.id"
              :label="item.name">
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>

      <div
        slot="footer"
        class="dialog-footer">
        <el-button @click="refundScenicDlgVisible = false">
          取 消
        </el-button>
        <el-button
          type="primary"
          @click="confirmScenicCheckWrapper();">
          <!-- 要考虑单个检票和批量检票两种情形 -->
          确 定
        </el-button>
      </div>
    </el-dialog>
    <el-dialog
      :visible.sync="visible"
      :before-close="handleClose"
      title="门票信息"
      width="80%">
      <div class="table-box">
        <el-form
          :inline="true"
          label-width="120"
          label-position="right"
          class="buyer-info">
          <el-form-item
            label="旅行社"
            v-if="orderData.groupIndividual === 2"
          >
            <span>{{ orderData.travelAgencyName }}</span>
          </el-form-item>
          <el-form-item :label="orderData.groupIndividual === 1 ? '预订人' : '导游'">
            {{ orderData.buyerName || '暂无' }}
          </el-form-item>
          <el-form-item label="手机号">
            {{ orderData.buyerPhone || '暂无' }}
          </el-form-item>
          <el-form-item label="证件类型">
            {{ orderData.buyerIdentifyType | paperType }}
          </el-form-item>
          <el-form-item label="购买人证件号">
            {{ orderData.buyerIdentify || '暂无' }}
          </el-form-item>
        </el-form>

        <el-table
          border
          ref="multipleTable"
          @selection-change="handleSelectionChange"
          :data="orderData.tickets">
          <el-table-column
            :selectable="selectable"
            type="selection"
            width="55">
          </el-table-column>
          <el-table-column
            width="80"
            label="序号"
            prop="id"
          >
            <template slot-scope="scope">
              {{ scope.row.id.toString().padStart(8,'0') }}
            </template>
          </el-table-column>
          <el-table-column
            prop="ticketNo"
            label="票号"
          >
          </el-table-column>

          <el-table-column
            prop="tname"
            label="票种"
          >
          </el-table-column>

          <el-table-column
            v-if="orderData.tickets&&orderData.tickets[0]&&orderData.tickets[0].batch_config_id"
            min-width="120"
            label="场次名称"
          >
            <template slot-scope="scope">
              <el-tag type="primary">
                {{ scope.row.batch_config.name }}
              </el-tag>
            </template>
          </el-table-column>

          <el-table-column
            width="80"
            label="票价"
          >
            <template slot-scope="scope">
              {{ (scope.row.price/scope.row.checkNum).toFixed(2) }}
            </template>
          </el-table-column>

          <el-table-column
            prop="guestName"
            label="游客姓名"
          >
          </el-table-column>
          <el-table-column
            prop="guestIdentify"
            label="身份证"
          >
          </el-table-column>
          <el-table-column
            width="100"
            prop="checkNum"
            label="检票人数"
          >
          </el-table-column>
          <el-table-column
            width="100"
            prop="payDateBegin"
            label="游玩时间"
          >
            <template slot-scope="scope">
              {{ scope.row.isNeedPlaytime?scope.row.payDateBegin:'无限制' }}
            </template>
          </el-table-column>
          <el-table-column
            width="80"
            label="状态"
          >
            <template slot-scope="scope">
              <el-tag :type="scope.row.status | ticketStatusColor">
                {{ scope.row.status | ticketStatus }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column
            width="80"
            prop="price"
            label="小计"
          >
          </el-table-column>

          <el-table-column
            width="80"
            label="操作"
          >
            <template
              slot-scope="scope">
              <el-button
                type="primary"
                :disabled="forceCheck?false:scope.row.status !== 'WAIT_USE'"
                @click="handleRefundTicketWrapper(scope.row)">
                检票
              </el-button>
            </template>
          </el-table-column>
        </el-table>

        <div class="btn-wrap">
          <el-checkbox
            v-model="forceCheck"
            @change="handleChange">
            强制检票
          </el-checkbox>

          <div>
            <el-button
              type="primary"
              @click="toggleSelection">
              全选 / 取消全选
            </el-button>
            <el-button
              type="primary"
              @click="groupCheckWrapper">
              批量检票
            </el-button>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { checkTickets } from '@/api/order'
import { getManualTicketCheckScenic } from '@/api/systemConfig'
import checkPermission from '@/utils/checkPermission'
import posMixin from '@/pages/common/posMixin'

const posPayArray = ['银行卡', '银联扫码', '支付宝', '微信']

export default {
  mixins: [posMixin],
  computed: {
    payChannelOptions () {
      return this.$store.state.app.payChannelOptions
    },
    scenicName () {
      return this.$localStore.get('scenicName') || this.$store.state.user.scenicName
    },
    showPosQuery () {
      return (this.scenicName === '狼山景区' || this.scenicName === '军山景区') && this.orderData.payChannel && (this.orderData.payChannel.indexOf('中行') > -1 || posPayArray.indexOf(this.orderData.payChannel) > -1) && this.orderData.status !== 'CANCELED'
    }
  },
  created () {
    this.getConfigManualTicketCheckScenic() // 获取是否开启检票时选择景点功能
  },
  data () {
    return {
      visible: false,
      refundScenicDlgVisible: false, // 控制检票时选景点的弹窗
      refundScenicRadio: 1, // 简单选择demo
      selectedRefundScenicId: -1, // refundScenicArr里选中的id，也即参数里要传的scenic_id
      refundScenicArr: [], // 待选的景点数组
      scenicScopeRowData: {}, // confirm里的scope.row即data
      titleOfScenicDlg: '选择景点检票',
      /* 值'选择景点检票'或'选择景点批量检票',这个很重要,根据文案选择不同api发请求 */
      config_manual_ticket_check_scenic: 0,
      /* refundScenicArr的例子数据：[{'id': 666, 'name': '上海景区'}, {'id': 888, 'name': '杭州景区'}] */
      orderData: [],
      selectTickets: [],
      currentTicket: null,
      cancel_pay_channel: '',
      cancel_manager: null,
      isRefundPosInfo: null,
      isRefunding: false,
      forceCheck: false
    }
  },
  methods: {
    async getConfigManualTicketCheckScenic () {
      let isManualTicketCheckScenic = await getManualTicketCheckScenic() /* 1 or 0 */
      this.config_manual_ticket_check_scenic = isManualTicketCheckScenic
      console.log('是否开启人工检票时选择景点设置：', isManualTicketCheckScenic)
    },
    handleChange (val) {
      this.$refs.multipleTable.clearSelection()

      if (val) {
        this.$confirm('确定强制检票？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {

        }).catch(() => {
          this.forceCheck = false
        })
      }
    },
    checkRefundVisible (item) {
      if (item.status !== 'USED' && item.status !== 'CANCELED') return true
      return (item.status === 'USED' || item.status === 'CANCELED') && checkPermission('ticket_sale:refund_checked')
    },
    show (data) {
      this.visible = true
      this.orderData = JSON.parse(JSON.stringify(data))
      this.cancel_pay_channel = ''
    },
    handleClose () {
      this.visible = false
      this.forceCheck = false
    },
    refundTicketScenic (data) {
      /* 用来替代refundTicket(data)，原来是确认，现在是弹窗展示票里的景点，选择其中一个景点，增加选择景点的功能
       * data.ticketScenic 是个数组（大多只包含一个元素），测试数据：
       * data.ticketScenic = [{"last_checkTime":"1970-12-31T16:00:00.000+0000","scenic_id":2,"passed_times":0,"checked_times":0,"change_flag":0,"scenic_name":"上海景区","single_pass_times":1,"id":5316970,"ticket_id":4236289,"checkLimitTimes":1}]
       */
      this.refundScenicArr = data.ticketScenic.map(({ scenic_id: id, scenic_name: name }) => ({ id, name }))
      this.selectedRefundScenicId = this.refundScenicArr?.[0].id // 默认选中第一个id
      console.log('简化后的景点数组：', JSON.stringify(this.refundScenicArr))
      this.scenicScopeRowData = data // 待confirmScenicCheck中发请求时调用
      /**
       * 票的景点们信息数组refundScenicArr里我只保留了id和name，方便一点，需要更多属性的话，可以再加；或直接使用data.ticketScenic
       * console.log('票绑定的所有景点详细信息：', JSON.stringify(data.ticketScenic))
       * console.log('票绑定的头个景点的scenic_id：', data.ticketScenic[0].scenic_id)
       * console.log('scenicScopeRowData:', data)
       */
      this.refundScenicDlgVisible = true
      this.titleOfScenicDlg = '选择景点检票' /* 二次确定时按照文案选择不同api发请求 */
      /* 但此处不发检票请求，待confirmScenicCheck里二次确定 */
    },
    confirmScenicCheck () {
    // handle选景点检票弹窗的确定(这里只处理单个检票的情况,批量检票另有函数)
      this.$confirm('确定检票吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true
      }).then(() => {
        console.log('确定检票了, 景点的scenicId为：', this.selectedRefundScenicId)
        /*  20230517【东方绿洲】:线下客户端-售票管理-人工检票中，检票时增加景点选择，接口路径不变，增加一个参数scenicId,单选 */
        checkTickets({ is_force_check: this.forceCheck ? 1 : 0, list: [this.scenicScopeRowData.ticketNo], scenicId: this.selectedRefundScenicId }).then(res => {
          this.$message.success('操作成功')
          this.handleClose()
          setTimeout(() => {
            this.$emit('updateList')
          }, 1000)
        })
        this.refundScenicDlgVisible = false // 隐藏窗口
      }).catch(() => {
        console.log('放弃检票了')
        this.cancel_manager = null
        this.refundScenicDlgVisible = false // 隐藏窗口
      })
    },
    handleRefundTicketWrapper (data) {
    // 根据manual_ticket_check_scenic字段决定是使用之前的refundTicket(data)还是用可以选景点的检票refundTicketScenic(data)
      if (Number(this.config_manual_ticket_check_scenic) === 1) {
        this.refundTicketScenic(data)
      } else {
        this.refundTicket(data)
      }
    },
    refundTicket (data) {
      this.$confirm('确定检票吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true
      }).then(() => {
        checkTickets({ is_force_check: this.forceCheck ? 1 : 0, list: [data.ticketNo] }).then(res => {
          this.$message.success('操作成功')

          this.handleClose()

          setTimeout(() => {
            this.$emit('updateList')
          }, 1000)
        })
      }).catch(() => {
        this.cancel_manager = null
      })
    },
    handleSelectionChange (val) {
      this.selectTickets = val
    },
    toggleSelection () {
      this.$refs.multipleTable.toggleAllSelection()
    },
    selectable (row, index) {
      return this.forceCheck ? row.status !== 'CANCELED' : row.status === 'WAIT_USE'
    },
    /* 现在废弃检查，允许不一致，但取交集 */
    checkTicketScenicSame () { /* 判断批量检票所选择的票们景点是否一致 */
      const ticketScenicList = this.selectTickets[0].ticketScenic // 取第一张门票的景区信息作为参照

      for (let i = 1; i < this.selectTickets.length; i++) {
        const currentTicketScenicList = this.selectTickets[i].ticketScenic

        // 如果景区列表长度不同，或者有其中一个景区的id和参照不同，则认为不一致
        if (currentTicketScenicList.length !== ticketScenicList.length) {
          return false
        }
        for (let j = 0; j < currentTicketScenicList.length; j++) {
          if (currentTicketScenicList[j].scenic_id !== ticketScenicList[j].scenic_id) {
            return false
          }
        }
      }

      return true // 如果没有找到不同的情况，则认为是一致的
    },
    groupCheckWrapper () {
      if (!this.selectTickets.length) {
        this.$message.error('请选择门票')
        return
      }
      /**
       * 现在批量检票也要选择景点
       * 根据manual_ticket_check_scenic字段决定是使用之前的refundTicket(data)还是用可以选景点的检票refundTicketScenic(data)
       */
      if (Number(this.config_manual_ticket_check_scenic) !== 1) {
        this.groupCheck() // 不选景点
      } else {
        /**
         * 批量检票时选景点
         * this.selectTickets是选的this.orderData.tickets中的一些票
         * console.log(JSON.stringify(this.selectTickets))
         * console.log('orderData.tikets[].ticketScenic[]:', this.selectTickets[0].ticketScenic)
         * this.orderData.tickets[0].ticketScenic 例如 { scenic_name: '上海景区', scenic_id: 2 }
         * console.log(JSON.stringify(this.orderData.tickets.map(ticket => ticket.ticketScenic))
         */
        this.titleOfScenicDlg = '选择景点批量检票' /* 二次确定时按照文案选择不同api发请求 */
        /* if (!this.checkTicketScenicSame()) { // 检查所选票们景点是否一致
         *   this.$message.error('所选票景点不一致，请确保人工检票时所选票绑定的景点一致！')
         *   return
         * }
         * console.log('this.selectTickets:', JSON.stringify(this.selectTickets))
         * const ticketScenicArr = this.selectTickets.flatMap(ticket => ticket.ticketScenic.map(({ scenic_id: id, scenic_name: name }) => ({ id, name })))
         * 现在改为取景点的'交集'，允许其景点不一致
         */
        const ticketScenicArr = this.selectTickets
          .map(ticket => ticket.ticketScenic.map(({ scenic_id: id }) => id))
          .reduce((prev, curr) => prev.filter(id => curr.includes(id)))
          .map(id => {
            const name = this.selectTickets[0].ticketScenic.find(scenic => scenic.scenic_id === id).scenic_name
            return { id, name }
          })
        console.log('ticketScenicArr:', ticketScenicArr)
        /**
           * 思路：
           * 1.使用 map() 方法提取每个 ticket 的 ticketScenic 属性中的 scenic_id 数组。
           * 2.使用 reduce() 方法将所有这些数组的交集提取出来。
           * 3.使用 map() 方法将交集转换成 { id, name } 格式的数组。
           * 上述代码中，由于所有的 ticketScenic 数组都是相同格式的，我们只需要使用 this.selectTickets[0] 来获取一个 ticket 的信息即可。
           * 如果确认所有 ticketScenic 数组都相同，那么以上代码可以正常运行。
           */
        if (ticketScenicArr.length < 1) {
          this.$message.error('所选票景点没有交集，无法批量检票！')
          return
        }
        const uniqueTicketScenicArr = Array.from(ticketScenicArr.reduce((map, obj) => map.set(obj.id, obj), new Map()).values())
        /**
         * console.log(JSON.stringify(ticketScenicArr))
         * ticketScenicArr样例数据[{"id":2,"name":"上海景区"},{"id":2,"name":"上海景区"},{"id":2,"name":"上海景区"},{"id":2,"name":"上海景区"},{"id":2,"name":"上海景区"}]
         * 需要对其按照id进行去重为uniqueTicketScenicArr：[{"id":2,"name":"上海景区"}
         * console.log(JSON.stringify(uniqueTicketScenicArr))
         */
        this.refundScenicArr = uniqueTicketScenicArr
        this.selectedRefundScenicId = this.refundScenicArr?.[0].id // 默认选中第一个id
        // 这个请求和单个票的请求不一样
        this.refundScenicDlgVisible = true
      }
    },
    confirmScenicCheckWrapper () {
    // 可能是单个的检票，也可能是批量检票，这里处理两种情形
      if (this.titleOfScenicDlg === '选择景点检票') {
        this.confirmScenicCheck() // 单个检票
        return
      }
      // 下面是文案为选择景点'批量'检票的情况,list需要传不同的数组
      this.$confirm('确定批量检票吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true
      }).then(() => {
        console.log('确定批量检票了, 景点的scenicId为：', this.selectedRefundScenicId)
        /*  20230517【东方绿洲】:线下客户端-售票管理-人工检票中，检票时增加景点选择，接口路径不变，增加一个参数scenicId,单选 */
        const tickets = this.selectTickets.map(i => i.ticketNo)
        checkTickets({ is_force_check: this.forceCheck ? 1 : 0, list: tickets, scenicId: this.selectedRefundScenicId }).then(res => {
          this.$message.success('操作成功')
          this.handleClose()
          setTimeout(() => {
            this.$emit('updateList')
          }, 1000)
        })
        this.refundScenicDlgVisible = false // 隐藏窗口
      }).catch(() => {
        console.log('放弃检票了')
        this.cancel_manager = null
        this.refundScenicDlgVisible = false // 隐藏窗口
      })
    },
    groupCheck () {
      if (!this.selectTickets.length) {
        this.$message.error('请选择门票')
        return
      }

      this.$confirm('确定检票吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true
      }).then(() => {
        const tickets = this.selectTickets.map(i => i.ticketNo)

        checkTickets({ is_force_check: this.forceCheck ? 1 : 0, list: tickets }).then(res => {
          this.$message.success('操作成功')

          this.handleClose()

          setTimeout(() => {
            this.$emit('updateList')
          }, 1000)
        })
      }).catch(() => {
        this.cancel_manager = null
      })
    }
  },
  beforeDestroy () {
    this.killAllPosProcess()
  }
}
</script>

<style lang="scss" scoped>
.btn-wrap{
  display: flex; justify-content: space-between; padding: 10px 0;
}
</style>
