import {ref, onMounted, onUnmounted} from 'vue'
import {createOrder as createOrderApi, getCardPrice, queryOrder} from "@/api/system/user";
import {createEventHook, useIntervalFn, useLocalStorage, useTimeout} from "@vueuse/core";
import mxConst from "@/common/mxConst";
import _ from "lodash";
import {func, number} from "@/uni_modules/uv-ui-tools/libs/function/test";
import {useTransfer} from "@/hooks/useTransfer";
import {toast} from "@/uni_modules/uv-ui-tools/libs/function";
import config from "@/config";
import {useEnvStore} from "@/hooks/useEnvStore";
import {useUserStore} from "@/hooks/useUserStore";

export const paymentState = {
    NOTPAY: 'NOTPAY',
    SUCCESS: 'SUCCESS',
    CLOSED: 'CLOSED'
}

export const defaultPaymentOptions = {
    onSucceed: () => {
        const {transferTo} = useTransfer()
        uni.hideLoading()
        uni.showModal({
            content: '支付成功, 请查收短信并绑定VIP卡',
            confirmText: '去绑卡',
            success: res => {
                if (res.confirm) {
                    transferTo(mxConst.routes.activate)
                }
            }
        })
    },
    onTimeout: (msg) => {
      uni.hideLoading()
        uni.showModal({
            content: msg,
            showCancel: false
        })
    },
    onFailed: () => {
      uni.hideLoading()
        // only print error info on console.
        console.error(...arguments)
    }
}

export const usePayment = function (options = defaultPaymentOptions) {

    const orderSucceed = createEventHook()
    const orderFailed = createEventHook()
    const orderTimeout = createEventHook()
    const price = ref(798)
    const outTradeNo = useLocalStorage(mxConst.keyOutTradeNo, '')
    const interval = ref(1500)
    let queryTimes = 8;
    let iframe = null
    let lock = false

    onMounted(() => loadPrice())
    onUnmounted(() => {
        // clear resources
        outTradeNo.value = null
        clearResultFrame()
    })

    const payment = async function () {
        if (lock) return toast('支付中，请稍候...')
        uni.showLoading({title:"", mask: true})
        try {
            lock = true // will release while trigger func be called
            const {h5url, outTradeNo: no} = await createOrder()
            if (h5url && no) {
                outTradeNo.value = no
                clearResultFrame()
                queryTimes = 8;
                iframe = await createResultFrame(h5url)
            } else {
                triggerFailed('Payment: create order failed', h5url, no)
            }
        } catch (e) {
            triggerFailed('Payment: exception', e)
        }
    }

    const iosPayment = async function () {
        const {isWap2App} = useEnvStore();
        const {token} = useUserStore();
        if (isWap2App.value && window.webviewBridge) {
            uni.showLoading({
                title: "",
            });
            const { orderId } = await createOrder('ios');
            uni.hideLoading();
            if (orderId) {
                let eventArgs = []
                window.webviewBridge.applePay({
                    orderId,
                    token: token.value,
                    baseUrl: config.serverBaseUrl + '/front/ecard/iosVerifyResult'
                }).then(res => {
                    if (res === "支付成功") {
                        eventArgs = ['交易成功', orderId]
                        triggerSucceed(...eventArgs)
                    } else {
                        eventArgs = ['支付失败', orderId]
                        triggerFailed(...eventArgs)
                    }
                });
            }
        } else {
          toast("请在app中操作");
        }
    }


    const loadPrice = async function () {
        const res = await getCardPrice()
        const val = _.get(res, 'data[0].price')
        if (number(val)) price.value = val / 100
    }

    const createOrder = async function (type) {
        const {data: {h5url, outTradeNo, orderId}} = await createOrderApi({totalFee: price.value, type})
        return {h5url, outTradeNo, orderId}
    }

    const createResultFrame = async function (h5url) {
        const { isH5, isWap2App } = useEnvStore();
        if (isH5.value) {
          await useTimeout()
          const iframe = document.createElement('iframe');
          const style = `width:0px;height:0px;position: absolute;opacity: 0;z-index: -1;outline:none;border:none;`;
          iframe.setAttribute('style', style);
          iframe.setAttribute('sandbox', 'allow-scripts allow-top-navigation allow-same-origin');
          iframe.style.position = 'absolute';
          iframe.src = h5url;
          iframe.onload = () => checkOrderStatus()
          iframe.onerror = () => console.error('Payment: iframe加载失败')
          document.body.appendChild(iframe);
          return iframe
        } else if (isWap2App.value) {
          const style = {
            webviewBGTransparent: true,
            opacity: 0,
            render: 'always',
            zindex: -1,
            width: '1px',
            height: '1px',
            top:'0px',
            left:'0px',
            additionalHttpHeaders:{
              Referer: config.paySiteUrl,
            }
          };
          const wv = plus.webview.create(h5url, 'wechatPayWebview', style);
          wv.addEventListener('loaded', (e) => {
            checkOrderStatus();
          }, false);
          wv.show();
          return wv;
        }
    }

    const checkOrderStatus = async function () {
        if (!outTradeNo.value) return
        const {pause} = useIntervalFn(() => {
            const no = outTradeNo.value // double check
            if (!no) return pause()
            if (queryTimes-- <= 0) {
              triggerTimeout('支付超时')
              return pause();
            }
            // 由于这个请示不是规范返回，request配置为 custom: {toast: false}
            queryOrder({outTradeNo: no})
                .then()
                .catch(({tradeState}) => {
                    console.log(no, tradeState)
                    let eventArgs = []
                    switch (tradeState) {
                        case paymentState.NOTPAY:
                            // user payment not complete, do nothing
                            // waiting for next order check
                            break;
                        case paymentState.SUCCESS:
                            // success
                            outTradeNo.value = ''
                            pause()
                            eventArgs = ['交易成功', no]
                            triggerSucceed(...eventArgs)
                            break
                        case paymentState.CLOSED:
                            // timeout
                            outTradeNo.value = ''
                            pause()
                            eventArgs = ['支付超时', no]
                            triggerTimeout(...eventArgs)
                            break
                        default:
                            // unexpected status
                            outTradeNo.value = ''
                            pause()
                            eventArgs = [`未知交易状态：${tradeState}`, no]
                            triggerFailed(...eventArgs)
                            break
                    }
                });
        }, interval)
    }

    const triggerSucceed = function () {
        lock = false
        if (func(options?.onSucceed)) options.onSucceed(...arguments)
        else orderSucceed.trigger(...arguments)
    }
    const triggerTimeout = function () {
        lock = false
        if (func(options?.onTimeout)) options.onTimeout(...arguments)
        orderTimeout.trigger(...arguments)
    }
    const triggerFailed = function () {
        lock = false
        if (func(options?.onFailed)) options.onFailed(...arguments)
        orderFailed.trigger(...arguments)
    }

    const clearResultFrame = function () {
      const { isH5, isWap2App } = useEnvStore();
        if (iframe) {
          if (isH5.value) {
            document.body.removeChild(iframe)
          } else if (isWap2App.value) {
            iframe.close();
          }
          iframe = null;
        }
    }

    return {
        price,
        payment,
        iosPayment,
        onOrderSucceed: orderSucceed.on,
        onOrderFailed: orderFailed.on,
        onOrderTimeout: orderTimeout.on
    }
}