<template>
  <view class="pay">
    <view class="pay__time">
      <text class="pay__time__price">{{ orderAmt }}</text>
      <view v-if="overTime" class="pay__time__hour">
        支付剩余时间：
        <uni-countdown
          class="countdown"
          :second="displayInfo.periodSeconds"
          :show-day="false"
          @timeup="timeupOut"
        />
      </view>
      <text v-else>支付超时，订单关闭</text>
    </view>

    <view class="pay__button">
      <button
        v-for="(btnItem, btnIndex) in buttonList"
        :key="btnIndex"
        :type="btnItem.type"
        :class="btnItem.className"
        :loading="isPaying"
        @click="onButtonClick(btnItem)"
      >
        {{ btnItem.name }}
      </button>
    </view>
    <view class="placeholder" />
    <tougdunCanvas />
  </view>
</template>

<script>
import authApi from "@/api/address.api";
import { uniCountdown } from "@dcloudio/uni-ui";
import { saTrackEvent } from "@/utils/sa";
import tougdunCanvas from "@/components/tougdunCanvas.vue";
import { param, debounce } from "@/utils/index";
import { queryPayInfo, prepay, queryPayStatus, pay } from "@/api/pay.api.js";
import { codeArr } from "@/pages/pay/STATIC_DATA.js";
import * as cfg from "./config";
import { paymentConfig, mpConfig } from "@/utils/mpConfig/types";
export default {
  components: {
    uniCountdown,
    tougdunCanvas
  },
  data() {
    return {
      orderNo: null, // 订单编号
      isPaying: false, // 是否支付中的状态
      payType: paymentConfig.payType, // 默认的支付方式
      openId: "", // 支付依赖的openId
      btnType: cfg.SURE_BTN, // 初始化按钮状态

      displayInfo: {
        orderAmt: null
      }
    };
  },
  computed: {
    buttonList() {
      return cfg.BUTTON_CONFIG[this.btnType];
    },
    overTime() {
      return this.btnType !== cfg.TMOT_BTN;
    },
    // 留着入口，实际支付金额
    orderAmt() {
      return this.displayInfo.orderAmt;
    }
  },
  onLoad({ orderNo }) {
    this.orderNo = orderNo || uni.getStorageSync("orderNo");
    uni.setStorageSync("orderNo", this.orderNo);
    this.queryPayInfo();
  },
  methods: {
    /***
     * 查询页面展示信息,暂时只有，金额，支付时间等
     * return null
     */
    async queryPayInfo() {
      uni.showLoading({ title: "加载中..." });
      const [data, error] = await queryPayInfo({
        orderNo: this.orderNo,
        isUsedMergePayMethod: false // 是否开启组合支付
      });

      if (error && codeArr.indexOf(error?.response?.businessCode) < 0) {
        uni.hideLoading();
        return this.payResult("Fail", error?.msg);
      }
      this.setPayTypeEvent(this.filterPayMethods(data?.payMethods));
      this.displayInfo = this.beforeFilterData(data?.displayInfo);
      uni.hideLoading();
    },
    filterPayMethods(payMethods) {
      const payItem = payMethods.find(item => item.isDefault);
      return payItem?.method;
    },
    setPayTypeEvent(payType) {
      this.payType = payType;
      if (payType === cfg.VIRTUAL_PAY) {
        this.btnType = cfg.ZREO_BTN;
        return;
      }
      this.btnType = cfg.SURE_BTN;
    },
    /**
     * 过滤展示信息，触发一些初始化操作
     * 处理之后返回参数
     * return info:object
     */
    beforeFilterData(info = {}) {
      // 初始化-支付时间小于0，支付已经过期
      if (info?.periodSeconds <= 0) {
        this.timeupOut();
      }
      return info;
    },
    onButtonClick(btnItem) {
      this[btnItem.event](btnItem);
    },
    // 支付事件触发
    nextAction: debounce(function(btnItem) {
      this.sendNextAction(btnItem);
      this.paymentEvent(this.payType);
    }, 500),
    async paymentEvent(payType) {
      this.isPaying = true;
      const { isNext } = await this.beforePayCheck();
      if (isNext) {
        try {
          const paramsData = await this.getPayParams(payType); // 获取预支付参数
          const { orderInfo } = await this.prepay(paramsData); // 获取支付参数
          const { status } = await this.requestPayment(orderInfo, paramsData);
          status && this.queryPayStatus(); // 支付成功之后的回调用
          this.isPaying = false;
        } catch (err) {
          console.log("错误信息================>", err);
          this.isPaying = false;
          if (err?.toast) return this.$api.msg(err.message);
          this.payResult("Fail", err.message);
        }
      } else {
        this.isPaying = false;
      }
    },
    async prepay(paramsData) {
      const [data, error] = await prepay(paramsData);
      if (!error) {
        let orderInfo = null;
        // 享花卡或者0元付等依赖的参数--暂时只有0元付
        if (paramsData.payMethod === cfg.VIRTUAL_PAY) {
          orderInfo = data.flowOrderNo;
        } else {
          // 第三方支付依赖的参数-百度，支付宝，等....
          /* #ifdef MP-ALIPAY */
          orderInfo = data.aliPayInfo?.order_string;
          /* #endif */
          /* #ifdef MP-BAIDU */
          orderInfo = data?.baiduPayInfo;
          /* #endif */
        }
        return { orderInfo };
      }
      return Promise.reject({ message: error.msg });
    },
    async getPayParams(payType) {
      const openId = await this.getOpenId();
      return {
        openId,
        ocrAuth: { isH5: false },
        orderNo: this.orderNo,
        payMethod: payType,
        payCouponId: "", // 下单使用优惠卷id
        mergePayPretreatmentId: "",
        appMiniId: ""
      };
    },
    /***
     * 支付之前校验是否可以进行支付
     * @params null
     * @return { isNext: 校验是否通过 }
     */
    beforePayCheck() {
      return new Promise(resolve => {
        if (!this.overTime) {
          this.$api.msg("订单已超时！");
          return resolve({ isNext: false });
        } // 检测订单是否超时
        return resolve({ isNext: true });
      });
    },
    /***
     * 拉起支付
     * @params orderInfo: 支付所需要的参数信息, type: string|object
     * @retrun type: promise
     */
    async requestPayment(orderInfo, paramsData) {
      return new Promise((resolve, reject) => {
        console.log("================>拉起支付的参数", orderInfo, paramsData);
        // 拉起非第三方支付，0元付，或者享花卡，组合支付等
        if (paramsData.payMethod === cfg.VIRTUAL_PAY) {
          pay({ ...paramsData, flowOrderNo: orderInfo }).then(([, error]) => {
            if (error) {
              return reject({ status: false, message: error });
            }
            resolve({ status: true, message: "支付成功", isGroup: false }); // isGroup是否是组合支付，如支付成功之后再次拉起第三方支付
          });
          return;
        }
        // 第三方支付
        uni.requestPayment({
          provider: mpConfig.provider,
          orderInfo,
          success: result => {
            console.log("=======================>支付result", result);
            /* #ifdef MP-ALIPAY */
            const status = result?.errMsg === "requestPayment:ok";
            if (result?.resultCode === "9000") {
              return resolve({ status, message: "支付成功", ...result });
            }
            /* #endif */

            /* #ifdef MP-BAIDU */
            if (result) {
              return resolve({ status: true, message: "支付成功", ...result });
            }
            /* #endif */
            return reject({ status: false, toast: true, message: result.memo, ...result });
          },
          fail: error => {
            console.log("=======================>支付error", error);
            /* #ifdef MP-ALIPAY */
            reject({ status: false, message: "支付失败", ...error });
            /* #endif */
            /* #ifdef MP-BAIDU */
            reject({ status: false, message: error.errMsg });
            /* #endif */
          }
        });
      });
    },
    /***
     * 查询支付状态，支付成功到支付成功页
     * 支付助状态如果有延迟需要跳转到支付中的页面
     */
    async queryPayStatus() {
      const [{ payStatus }, error] = await queryPayStatus({ orderNo: this.orderNo });
      if (error) return this.payResult("Fail", error.msg); // 如果有错误信息直接跳转到错误页
      if (+payStatus === 3) return this.payResult("Success"); // 支付成功跳转到支付成功页
      this.payResult("Loading"); // 如果支付状态有延迟，直接到支付中的页面
    },
    /***
     * @params null
     * @return promise(openId: string)
     */
    getOpenId() {
      return new Promise((resolve, reject) => {
        const vm = this;
        const openId = uni.getStorageSync(paymentConfig.openIdKey);
        if (openId) return resolve(openId);
        // #ifdef MP-BAIDU
        uni.getLoginCode({
          success: async function(res) {
            const result = await vm.getLoginCode(res);
            if (result) {
              return resolve(result);
            }
            reject({ message: "获取openId错误！" });
          },
          fail: err => {
            console.log("getLoginCode====================> fail", err);
          }
        });
        // #endif

        // #ifdef MP-ALIPAY
        uni.login({
          provider: mpConfig.provider,
          scopes: "auth_base",
          success: async function(res) {
            const result = await vm.getLoginCode(res);
            if (result) {
              return resolve(result);
            }
            reject({ message: "获取openId错误！" });
          },
          fail: err => {
            console.log("login====================> fail", err);
          }
        });
        // #endif
      });
    },
    /**
     * 获取最新openId
     * 以防在支付时清除缓存之后无法支付
     * @params res uni.login返回code码
     */
    async getLoginCode(res) {
      const [data, error] = await authApi.login({ code: res.code });
      if (!error) {
        const result = data[paymentConfig.openIdKey];
        uni.setStorageSync(paymentConfig.openIdKey, result);
        return result;
      }
      return null;
    },
    timeupOut() {
      this.btnType = cfg.TMOT_BTN;
      console.log("timeupOut=============>");
    },
    /**
     * 支付成功｜失败中转页
     * @params type: Fail | Success
     * @params error: Fail时的错误信息
     */
    async payResult(type, error) {
      const queryParams = {
        orderNo: this.orderNo,
        amount: this.orderAmt,
        reason: error,
        payType: this.payType,
        freeAmount: 0
      };
      uni.redirectTo({ url: `/pages/pay/pay${type}${param(queryParams, true)}` });
    },
    goHome() {
      uni.switchTab({
        url: "/pages/index/index"
      });
    },
    goOrderDetail() {
      uni.redirectTo({
        url: `/pages/order/orderDetail?orderNo=${this.orderNo}`
      });
    },
    /******************************************************************************************/
    /******************************************************************************************/
    /***********************************神策埋点-START*******************************************/
    /******************************************************************************************/
    // 确认支付埋点
    sendNextAction(btnItem) {
      console.log(btnItem, "=================>=================>=================>");
      saTrackEvent("PD_YXMMACP_UserClickCashierConfirmPaymentBtn", {
        order_id: this.orderNo,
        pay_method: cfg.TACK_PAY_BUTTON_CLICK[this.payType],
        vcc_state: "",
        buttons_name: btnItem.name
      });
      uni.reportAnalytics("c_cashierconfirmpaymentbtn", {
        order_id: this.orderNo,
        pay_method: cfg.TACK_PAY_BUTTON_CLICK[this.payType],
        vcc_state: "",
        buttons_name: btnItem.name
      });
    }
    /******************************************************************************************/
    /*************************************神策埋点-END******************************************/
    /******************************************************************************************/
  }
};
</script>

<style lang="scss" scoped src="./index.scss"></style>
