<!-- 初始：8.x分支中1.4.204版本的OrderInfo.vue -->
<template>
  <el-card>
    <div
      slot="header"
      class="card-title"
      style="display: flex">
      <div class="top-title">订单明细</div>
      <!-- <el-button
        type="text"
        @click="distinctOrder">
        优惠/说明
      </el-button> -->
    </div>
    <div>
      <div class="is-flex">
        <div class="amount-info">
          <span class="item">实付金额：
            <el-input-number
              :min="0"
              :precision="2"
              :controls="false"
              v-model.number="actualMoney"></el-input-number>
          </span>
          <span class="item">下单备注：
            <el-input
              clearable
              v-model="createOrderRemark"
              style="width:200px"></el-input>
          </span>
        </div>
        <div class="pay-channel-wrap">
          <label class="text">支付方式：</label>
          <el-radio-group
            fill="#379143"
            class="tags-btn"
            @change="$localStore.set('retailPayment',$event)"
            v-model="payChannel"
            border>
            <el-radio
              border
              v-for="val in payChannelOptions"
              :key="val"
              :value="val"
              :label="val"></el-radio>
          </el-radio-group>
        </div>
      </div>

      <div class="btn-wrap">
        <span class="item price">总数：<b>{{ totalCount }}</b> 张</span>
        <span class="item price">总价：<b>{{ orderPrice }}</b> 元</span>
        <span class="item price">{{ payBack>0?'找零':'还需支付' }}：<b>{{ Math.abs(payBack) }}</b> 元</span>
        <span class="item">
          <PrintSmallTicketCheckbox v-model="autoPrintSmallTicket"></PrintSmallTicketCheckbox>
          <el-checkbox
            v-model="autoPrint"
            style="margin:10px"
            @change="handleAutoPrintChange"
          >
            自动打印
          </el-checkbox>
        </span>
        <div class="opt-btns">
          <el-button
            @click="$emit('clear')">
            清空订单
          </el-button>
          <el-button
            type="primary"
            class="danger-btn item"
            :disabled="value.length === 0 || !payChannel"
            @click="handleConfirm">
            确认出票
          </el-button>
          <el-button
            type="primary"
            class="danger-btn item"
            v-if="payChannel === '现金' && currentTicket"
            @click="showBatchDialog">
            批量出票
          </el-button>
        </div>
      </div>
    </div>

    <el-table
      border
      :data="value">
      <el-table-column
        prop="ticketName"
        label="票种名称"
        width="180">
      </el-table-column>
      <el-table-column label="游玩日期">
        <template slot-scope="scope">
          {{ scope.row.playDateBegin }}
        </template>
      </el-table-column>
      <el-table-column
        prop="count"
        label="数量">
        <template slot-scope="scope">
          <el-input-number
            v-model="scope.row.count"
            :min="1"></el-input-number>
        </template>
      </el-table-column>
      <el-table-column
        prop="price"
        label="单价">
        <template slot-scope="scope">
          <span v-if="scope.row.discountPrice">
            {{ scope.row.originalPrice + scope.row.discountPrice }} <s style="color: #f56c6c;">{{ scope.row.originalPrice }}</s>
          </span>
          <span v-else>
            {{ scope.row.price }}
          </span>
        </template>
      </el-table-column>
      <el-table-column
        prop="total"
        label="小计">
        <template slot-scope="scope">
          <span v-if="scope.row.discountPrice">
            {{ numCalc(scope.row.count, scope.row.price, '*') + numCalc(scope.row.count, scope.row.discountPrice, '*') }} <s style="color: #f56c6c;">{{ numCalc(scope.row.count, scope.row.originalPrice, '*') }}</s>
          </span>
          <span v-else>
            {{ numCalc(scope.row.count, scope.row.price, '*') }}
          </span>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        width="160">
        <template slot-scope="scope">
          <el-button
            @click="showTouristList(scope.row)"
            type="text">
            门票列表
          </el-button>
          <el-button
            @click="distinctTicket(scope.row)"
            type="text">
            改价
          </el-button>
          <el-button
            @click="handleDelete(scope.row)"
            type="text">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 设置改价说明的弹框 -->
    <el-dialog
      title="改价/说明"
      :visible.sync="showDiscountDialog"
      width="400px"
      @close="showDiscountDialog = false"
    >
      <el-form label-width="80px">
        <el-form-item label="票单价">
          <span>{{ discountInfo.ticketPrice }}</span>
        </el-form-item>
        <el-form-item label="改价金额">
          <el-input-number
            v-model.number="discountInfo.discountPrice"
            :precision="2"
            style="width: 200px"
          ></el-input-number>
          <el-tag type="warning" style="margin-top: 5px;">负数表示减价，正数表示加价</el-tag>
        </el-form-item>
        <el-form-item label="改价说明">
          <el-input
            type="textarea"
            v-model="discountInfo.discountDescription"
            :rows="3"
            placeholder="请输入说明"
          ></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="showDiscountDialog = false">取消</el-button>
        <el-button type="primary" @click="confirmDistinct">确定</el-button>
      </span>
    </el-dialog>

    <Confirm
      :create-order-remark="createOrderRemark"
      :tickets="tickets"
      :order-items="value"
      :form-data="formData"
      :order-price="orderPrice"
      :total-count="totalCount"
      :pay-channel="payChannel"
      :current-ticket="currentTicket"
      @complete="handleComplete"
      ref="confirm"></Confirm>
    <!-- 图片备注 -->
    <UploadImgList
      :picture-remarks="pictureRemarks"
      :update-remarks="updateRemarks"
      ref="uploadImgDialog">
    </UploadImgList>

    <!-- 游客列表 -->
    <TouristList
      :check-face="formData.checkWay === 4"
      :check-id="formData.checkWay === 3"
      :check-ticket-no="formData.checkWay === 5"
      :tourist-list="touristList"
      :update-tourist="updateTourist"
      ref="touristList"></TouristList>

    <!-- 批量出票弹框 -->
    <el-dialog
      title="批量出票"
      :visible.sync="batchDialogVisible"
      width="500px"
      :close-on-click-modal="false"
      @close="batchDialogVisible = false">
      <div v-loading="batchLoading" element-loading-text="正在批量出票中...">
        <el-alert
          title="批量出票过程中不要操作！！！"
          type="error"
          :closable="false"
          show-icon>
        </el-alert>

        <el-form label-width="140px" style="margin-top: 20px;">
          <el-form-item label="出票模式">
            <el-radio-group v-model="batchMode">
              <el-radio value="single" label="single">一码一人</el-radio>
              <el-radio value="multi" label="multi">一码多人</el-radio>
            </el-radio-group>
          </el-form-item>

          <el-form-item label="每张票人数">
            <el-input-number
              v-model="batchPeoplePerTicket"
              :min="1"
              :max="50"
              :disabled="batchMode === 'single'"
              style="width: 200px">
            </el-input-number>
            <span style="margin-left: 10px; color: #909399;">人</span>
            <el-tag v-if="batchMode === 'single'" type="info" style="margin-left: 10px;">一码一人固定为1</el-tag>
          </el-form-item>

          <el-form-item label="订单数量">
            <el-input-number
              v-model="batchOrderCount"
              :min="1"
              :max="500"
              style="width: 200px">
            </el-input-number>
            <span style="margin-left: 10px; color: #909399;">个订单</span>
          </el-form-item>

          <el-form-item v-if="batchLoading" label="出票进度">
            <el-progress :percentage="Math.round(batchProgress / batchTotal * 100)" :status="batchProgress === batchTotal ? 'success' : undefined"></el-progress>
            <span style="margin-left: 10px;">{{ batchProgress }} / {{ batchTotal }}</span>
          </el-form-item>
        </el-form>
      </div>

      <span slot="footer">
        <el-button @click="batchDialogVisible = false" :disabled="batchLoading">取消</el-button>
        <el-button
          type="primary"
          :loading="batchLoading"
          @click="batchCreateOrderLoop">
          {{ batchLoading ? '出票中...' : '开始批量出票' }}
        </el-button>
      </span>
    </el-dialog>
  </el-card>
</template>

<script>
import mixin from './mixin'
import { randomString } from '@/utils'
import Confirm from './Confirm'
import PrintSmallTicketCheckbox from '../common/PrintSmallTicketCheckbox'
import UploadImgList from '../common/uploadImgList'
import orderItemMixin from '../common/orderItemMixin'
import { createOrder, getSingleOrder } from '@/api/order'

/** 封装一个公共方法numCalc() 用于浮点数运算 */
// num1 num2传入两个值 symbol +-*/符号
const numCalc = (num1, num2, symbol) => {
  const str1 = num1.toString()
  const str2 = num2.toString()
  let result
  let str1Length
  let str2Length
  try {
    // 获取小数点后的精度
    str1Length = str1.split('.')[1].length
  } catch (error) {
    // 解决整数没有小数点方法
    str1Length = 0
  }
  try {
    str2Length = str2.split('.')[1].length
  } catch (error) {
    str2Length = 0
  }
  // 取两个数的最小精度，即小数点后数字的最大长度
  const maxLen = Math.max(str1Length, str2Length)
  // step将两个数都转化为整数至少小数点后移多少位
  const step = Math.pow(10, maxLen)

  switch (symbol) {
    case '+':
      // toFixed()根据最小精度截取运算结果
      result = ((num1 * step + num2 * step) / step).toFixed(maxLen)
      break
    case '-':
      result = ((num1 * step - num2 * step) / step).toFixed(maxLen)
      break
    case '*':
      result = (((num1 * step) * (num2 * step)) / step / step).toFixed(maxLen)
      break
    case '/':
      result = ((num1 * step) / (num2 * step)).toFixed(maxLen)
      break
    default:
      break
  }
  // 由于toFixed方法返回结果是字符串，还需要转回number输出
  return Number(result)
}

export default {
  mixins: [mixin, orderItemMixin],
  props: {
    value: {
      type: Array,
      default: () => []
    },
    currentTicket: {
      type: Object,
      default: () => null
    }
  },
  components: {
    Confirm,
    PrintSmallTicketCheckbox,
    UploadImgList
  },
  computed: {
    payBack () {
      if (this.actualMoney === undefined) {
        return -this.orderPrice
      } else {
        return this.$NP.minus(this.actualMoney, this.orderPrice)
      }
    },
    totalCount () {
      return this.value.reduce((init, item) => {
        return init + item.count
      }, 0)
    },
    orderPrice () {
      return this.value.reduce((init, item) => {
        let price = numCalc(item.count, item.originalPrice, '*')
        return numCalc(init, numCalc(price, item.discountPrice ? numCalc(item.discountPrice, item.count, '*') : 0, '+'), '+')
      }, 0)
    },
    tickets () {
      return this.value.reduce((init, item) => {
        return init.concat(item.tickets)
      }, [])
    }
  },
  data () {
    return {
      payChannel: '',
      actualMoney: 0,
      createOrderRemark: '',
      formData: {},
      pictureRemarks: [{
        idKey: randomString(),
        url: '',
        remark: ''
      }],
      autoPrint: this.$localStore.get('autoPrint'),
      autoPrintSmallTicket: this.$localStore.get('autoPrintSmallTicket'),
      showDiscountDialog: false,
      currentItem: null,
      // 批量出票
      batchDialogVisible: false,
      batchMode: 'single', // 'single' 一码一人, 'multi' 一码多人
      batchPeoplePerTicket: 1,
      batchOrderCount: 1,
      batchLoading: false,
      batchProgress: 0,
      batchTotal: 0,
      discountInfo: {
        ticketPrice: 0,
        discountPrice: 0,
        discountDescription: ''
      }
    }
  },
  methods: {
    numCalc,
    distinctOrder () {
      if (this.tickets.length === 0) {
        this.$message.warning('请先添加订单项')
        return
      }
      this.showDiscountDialog = true
    },
    distinctTicket (item) {
      this.currentItem = item
      this.discountInfo.ticketPrice = item.currentTicket.price
      this.discountInfo.discountPrice = item.discountPrice || 0
      this.discountInfo.discountDescription = item.discountDescription || ''
      this.showDiscountDialog = true
    },
    confirmDistinct () {
      const { discountPrice, discountDescription } = this.discountInfo

      this.$set(this.currentItem, 'discountPrice', discountPrice)
      this.$set(this.currentItem, 'discountDescription', discountDescription)
      this.currentItem.tickets.forEach(ticket => {
        this.$set(ticket, 'discountPrice', discountPrice)
        this.$set(ticket, 'price', ticket.originalPrice + discountPrice)
        this.$set(ticket, 'discountDescription', discountDescription)
      })
      this.showDiscountDialog = false
    },
    // 更新图片备注列表
    updateRemarks (data) {
      this.pictureRemarks = data
    },
    // 显示图片备注弹窗
    showUploadImgDialog () {
      this.$refs.uploadImgDialog.show()
    },
    changePayChannel (n) {
      if (this.confirmVisible) return

      let i = this.payChannelOptions.findIndex(channel => channel === this.payChannel)
      let l = this.payChannelOptions.length
      let j = (i - n + l) % l
      this.payChannel = this.payChannelOptions[j]
    },
    PageUp () {
      this.changePayChannel(1)
    },
    PageDown () {
      this.changePayChannel(-1)
    },
    handleDelete (item) {
      this.$confirm('确定删除吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$message({
          type: 'success',
          message: '删除成功!'
        })
        const idx = this.value.findIndex(i => i.keyId === item.keyId)
        this.value.splice(idx, 1)
      })
    },
    handleAutoPrintChange (val) {
      this.$localStore.set('autoPrint', val)
    },
    handleComplete () {
      this.$emit('clear')
      this.createOrderRemark = ''
      this.$localStore.get('defaultPayWay') && this.setPayWay()
      try {
        this.$parent.$parent.$refs.recentOrder && this.$parent.$parent.$refs.recentOrder.getOrderList()
      } catch (e) {
        console.warn('刷新最近订单失败', e)
      }
    },
    setPayWay () {
      const payment = this.$localStore.get('defaultPayWay') || this.payChannelOptions[0]

      this.payChannel = this.payChannelOptions.indexOf(payment) < 0 ? this.payChannelOptions[0] : payment
    },
    // 显示批量出票对话框
    showBatchDialog () {
      this.formData = this.$parent.$refs.formInfo.form
      this.batchDialogVisible = true
      this.batchMode = 'single'
      this.batchPeoplePerTicket = 1
      this.batchOrderCount = 1
      this.batchProgress = 0
      this.batchTotal = 0
    },
    // 构建批量出票参数
    buildBatchParams () {
      const params = JSON.parse(JSON.stringify(this.formData))
      const moment = require('moment')

      params.playDateBegin = moment(this.formData.playDateBegin).format('YYYY-MM-DD')
      params.playDateEnd = moment(this.formData.playDateEnd).format('YYYY-MM-DD')

      // 从currentTicket构建票务，不使用全局tickets
      const tickets = []
      const singlePrice = this.currentTicket.price
      const playDateBegin = params.playDateBegin
      const playDateEnd = params.playDateEnd

      if (this.batchMode === 'single') {
        // 一码一人：每张票一个人
        for (let i = 0; i < this.batchPeoplePerTicket; i++) {
          tickets.push({
            ticketTypeId: this.currentTicket.id,
            price: singlePrice,
            originalPrice: singlePrice,
            checkNum: 1,
            playDateBegin,
            playDateEnd,
            isDiscount: this.currentTicket.isDiscount || 0,
            batchConfigId: params.batchConfigId || '',
            guestName: '',
            guestPhone: '',
            guestIdentify: '',
            guestIdentifyType: 0,
            face: null,
            ticketNo: '',
            isStorage: 0,
            discountPrice: 0,
            discountDescription: ''
          })
        }
        params.price = this.$NP.times(singlePrice, this.batchPeoplePerTicket)
      } else {
        // 一码多人：一张票对应N人
        tickets.push({
          ticketTypeId: this.currentTicket.id,
          price: this.$NP.times(singlePrice, this.batchPeoplePerTicket),
          originalPrice: singlePrice,
          checkNum: this.batchPeoplePerTicket,
          playDateBegin,
          playDateEnd,
          isDiscount: this.currentTicket.isDiscount || 0,
          batchConfigId: params.batchConfigId || '',
          guestName: '',
          guestPhone: '',
          guestIdentify: '',
          guestIdentifyType: 0,
          face: null,
          ticketNo: '',
          isStorage: 0,
          discountPrice: 0,
          discountDescription: '',
          ticketOrderTravellers: [{
            name: '',
            idType: 0,
            idNum: '',
            mobile: ''
          }]
        })
        params.price = this.$NP.times(singlePrice, this.batchPeoplePerTicket)
      }

      params.tickets = tickets
      params.payChannel = '现金'
      params.sellDevice = (this.$parent.$refs.formInfo.sellerDevice && this.$parent.$refs.formInfo.sellerDevice.ip4) || ''
      params.createOrderRemark = this.createOrderRemark

      // 处理ticketNo和face
      params.tickets.forEach(ticket => {
        if (params.checkWay !== 5) {
          ticket.ticketNo = ''
          ticket.isStorage = 0
        } else {
          ticket.isStorage = 1
        }
        ticket.face = {
          faceImg: ticket.face
        }
        ticket.batchConfigId = params.batchConfigId || ticket.batchConfigId || ''
      })

      return params
    },
    // 校验批量出票输入
    validateBatchInput () {
      if (!this.currentTicket) {
        this.$message.error('请先选择票种')
        return false
      }
      if (!this.batchPeoplePerTicket || this.batchPeoplePerTicket < 1) {
        this.$message.error('请输入正确的每张票人数')
        return false
      }
      if (this.batchMode === 'multi' && this.batchPeoplePerTicket > 50) {
        this.$message.error('一码多人模式下每张票人数不能超过50')
        return false
      }
      if (!this.batchOrderCount || this.batchOrderCount < 1) {
        this.$message.error('请输入正确的订单数量')
        return false
      }
      return true
    },
    // 批量出票循环
    async batchCreateOrderLoop () {
      if (!this.validateBatchInput()) return

      const baseParams = this.buildBatchParams()
      this.batchLoading = true
      this.batchTotal = this.batchOrderCount
      this.batchProgress = 0

      for (let i = 0; i < this.batchOrderCount; i++) {
        try {
          const freshParams = JSON.parse(JSON.stringify(baseParams))
          const res = await createOrder(freshParams)
          this.batchProgress = i + 1

          // 每个订单成功后调用打印
          const order = res.data?.order
          if (order?.id) {
            getSingleOrder(order.id).then(res2 => {
              this.autoPrintSmallTicket && this.$printSmallTicket(order)
              const order2 = res2.data
              this.autoPrint && this.$print(order2)
            })
          }

          // 少量延时，避免并发问题
          if (i < this.batchOrderCount - 1) {
            await new Promise(resolve => setTimeout(resolve, 300))
          }
        } catch (e) {
          console.error('批量出票失败', e)
          this.$message.error(`第${i + 1}次出票失败: ${e.message || e.msg || '未知错误'}`)
          // 继续下一张
        }
      }

      this.batchLoading = false
      this.$message.success(`批量出票完成，成功出票 ${this.batchProgress} 次`)
      this.batchDialogVisible = false
      this.$emit('clear')
    }
  },
  watch: {
    orderPrice (val) {
      this.actualMoney = val
    },
    payChannelOptions: {
      handler (val) {
        if (val.length) {
          this.setPayWay()
        }
      },
      immediate: true
    }
  },
  mounted () {
    const payment = this.$localStore.get('defaultPayWay') || this.$localStore.get('retailPayment') || this.payChannelOptions[0]

    this.payChannel = this.payChannelOptions.indexOf(payment) < 0 ? this.payChannelOptions[0] : payment
  }
}
</script>

<style lang="scss" scoped>
.item {
  margin-left: 20px;
}

.price-info {
  padding: 10px 0;
  text-align: right;
  background: #fff;
}

.btn-wrap {
  display: flex;
  width: 100%;
  margin-bottom: 10px;
  font-size: 14px;
  justify-content: space-between;
  align-items: center;

  .el-input {
    display: inline-block;
    width: 100px;
  }
}
</style>
