package cn.pluss.platform.hf.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.pluss.platform.api.ResultCode;
import cn.pluss.platform.constants.Constant;
import cn.pluss.platform.dto.MemberScanPayDTO;
import cn.pluss.platform.dto.MerChantOrderDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.MerchantHfInfoMapper;
import cn.pluss.platform.merchantOrder.MerchantOrderService;
import cn.pluss.platform.pay.PayService;
import cn.pluss.platform.refundOrder.MerchantRefundOrderService;
import cn.pluss.platform.util.DateUtils;
import cn.pluss.platform.util.SnowFlakeUtil;
import cn.pluss.platform.util.StringUtil;
import cn.pluss.platform.ys.YsConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Strings;
import com.huifu.adapay.Adapay;
import com.huifu.adapay.model.AdapayCommon;
import com.huifu.adapay.model.MerConfig;
import com.huifu.adapay.model.Payment;
import com.huifu.adapay.model.Refund;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service("hfPayService")
@Slf4j
public class HfPayServiceImpl implements PayService {

    @Autowired
    MerchantHfInfoMapper merchantHfInfoMapper;



    @Value("${hf.pay.callBack}")
    private String callBack;


    @Setter(onMethod_ = {@Autowired, @Lazy})
    private MerchantOrderService merchantOrderService;


    @Setter(onMethod_ = {@Autowired, @Lazy})
    private MerchantRefundOrderService refundOrderService;

    private static String changeY2F(double price) {
        DecimalFormat df = new DecimalFormat("#0.00");
        return df.format(price);
    }

    private void init(String apiKey, String mockApiKey, String rsaPrivateKey) throws Exception {
        /**
         * debug 模式，开启后有详细的日志
         */
        Adapay.debug = false;

        /**
         * prodMode 模式，默认为生产模式，false可以使用mock模式
         */
        Adapay.prodMode = true;

        /**
         * 初始化商户配置，服务器启动前，必须通过该方式初始化商户配置完成
         * apiKey为prod模式的API KEY
         * mockApiKey为mock模式的API KEY
         * rsaPrivateKey为商户发起请求时，用于请求参数加签所需要的RSA私钥
         */
        if (Strings.isNullOrEmpty(apiKey)) {
            apiKey = "api_live_c5fbe553-0680-436a-a457-3252fc841697";
        }
        if (Strings.isNullOrEmpty(mockApiKey)) {
            mockApiKey = "api_test_ecb5e50f-c1bc-4854-af2d-eee4b98bcf6f";
        }
        if (Strings.isNullOrEmpty(rsaPrivateKey)) {
            rsaPrivateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAImujrgtJxw2Qm5TXNiRF4WuoYmyr37vpFX/LK4VUb0Qp7darJbNqNGvGBxbYmUccsKrAGyAJPwra71BtBEfTDsg4w0RO/6Wk4qx32ZHEaxpqYTLuOujUMvorL5AVr/SAlUtRlzwz82q4yQZxchYRGXlj3OP8iq1FzdXUxv+UeyjAgMBAAECgYAk7R04Blwr892DS3ZmWxus7fZDQRpSeCFiMysfkXY3uATTZ01MsOHrQwO7b0MHjUa2MTjO4NuKina97qZFxVgjSuByVrxkib+QY4vdqCL2I+tKH6qMSYlom0g8ybGWZrqQm2CzMFzf+ub4bpkJxINQ+7zjDsrRa5Lgk9B2xHkvoQJBAMG4hH7GWS67gYdpsTFtxbQiTrlreLAYJjwbaOhvpPiH3JaooPRcdceALe42eMZDAn5Mrg1jaA7/eM1iVMDXljMCQQC18fY9c1dHmLyOF3yaeVM+0kLrAyf//67xDV0QROYXo998vsIhpbeFm0cRTsjp4uXIq4W1KBAkBw0aqtEK/3/RAkBdl7czxMKrqF3BPZglSGK/T9/3B2xsr44xdhCuU9pBVOqHQ3tX9B/XPh9yupCJQTDAMm3Y/BD3RghoOjy2WrIvAkAGN0kBWnJt6MLwW88O+/wjFk3g94+jSFnytFEsoB34Ssn02hOJ0L6PWvm3lqh4jR7qlymPQdojUPZapeFUbdwxAkEAo+UYAbvDe1ewHpVtnbxMpWmtJeLRg8PlNhFfQjwfuaTOyyiuZU1pPtwUXjHsb4zqoA1QMR5vu0C0s2IpP8dljQ==";
        }

        MerConfig merConfig = new MerConfig();
        merConfig.setApiKey(apiKey);
        merConfig.setApiMockKey(mockApiKey);
        merConfig.setRSAPrivateKey(rsaPrivateKey);

        try {
            Adapay.initWithMerConfig(merConfig);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public JSONObject tradePay(MerchantOrder order, MerchantChannelStatus channel, MerchantBaseInfo merchant) {


        String account_type = "WECHAT";
        if (StringUtil.isNotEmpty(order.getScanType()) && "01".equals(order.getScanType())) {
            account_type = "wechatPay".equals(order.getPayTypeCode()) ? "WECHAT" : "aliPay".equals(order.getPayTypeCode()) ? "ALIPAY" : "UQRCODEPAY";
        } else {
            account_type = "wechatPay".equals(order.getPayTypeCode()) ? "WECHAT" : "aliPay".equals(order.getPayTypeCode()) ? "ALIPAY" : "UQRCODEPAY";
        }

        String transType = account_type.equals("WECHAT") ? "wx_lite" : account_type.equals("ALIPAY") ? "alipay_qr" : "union_qr";

        Map<String, Object> paymentParams = new HashMap<>();
        Map<String, String> deviceInfo = new HashMap<>();
        Map expendParams = new HashMap();

        if ("wx_lite".equals(transType)) {
            expendParams.put("open_id", order.getMercUserId());
            expendParams.put("wx_app_id", order.getAppletsAppid());
        } else {
            expendParams.put("buyer_id", order.getMercUserId());
        }


        MmerchantHfInfo hfInfo = merchantHfInfoMapper.selectByMerchantCode(merchant.getMerchantCode());
        MsgException.checkNull(hfInfo, "商户进件信息不存在");


        Boolean flag = false;
        if ("3".equals(hfInfo.getStatus()) || "4".equals(hfInfo.getStatus())) {
            flag = true;
        }

        if (!flag) {
            MsgException.check(true, "商户信息不完整");
        }

        String order_amt = changeY2F(order.getConsumeFee());

        deviceInfo.put("device_ip", order.getIp());
        paymentParams.put("app_id", hfInfo.getApp_id());
        paymentParams.put("order_no", order.getOrderNumber());
        paymentParams.put("pay_channel", transType);
        paymentParams.put("pay_amt", order_amt);
        paymentParams.put("goods_title", "收款码收款");
        paymentParams.put("goods_desc", "收款码收款");
        paymentParams.put("device_info", deviceInfo);
        //异步通知地址，url为http/https路径，服务器POST回调，URL 上请勿附带参数
        paymentParams.put("notify_url", callBack);
        paymentParams.put("expend", expendParams);

        log.info(paymentParams.toString());
        JSONObject resp = new JSONObject();

        Map<String, Object> adapay = null;
        JSONObject payData = new JSONObject();
        try {

            this.init(hfInfo.getLive_api_key(), hfInfo.getTest_api_key(), hfInfo.getPriv_key());
            adapay = Payment.create(paymentParams);
            log.info("payment result=" + JSON.toJSONString(adapay));
            if ("succeeded".equals(adapay.get("status"))) {
                if (!(StringUtil.isNotEmpty(order.getScanType()) && "01".equals(order.getScanType()))) {
                    cn.hutool.json.JSONObject expend = JSONUtil.parseObj(adapay.get("expend")).getJSONObject("pay_info");
                    if (Constant.PAY_TYPE_ALIPAY.equals(order.getPayTypeCode())) {
                        payData.put("source", JSONUtil.parseObj(adapay.get("expend")).get("qrcode_url"));
                    } else if (Constant.PAY_TYPE_WECHAT.equals(order.getPayTypeCode())) {
                        payData.put("payAppId", expend.get("appId"));
                        payData.put("payTimeStamp", expend.get("timeStamp"));
                        payData.put("paynonceStr", expend.get("nonceStr"));
                        payData.put("payPackage", expend.get("package"));
                        payData.put("paySignType", expend.get("signType"));
                        payData.put("paySign", expend.get("paySign"));
                    } else {
                        payData.put("redirectUrl", JSONUtil.parseObj(adapay.get("expend")).get("qrcode_url"));
                    }
                } else {
                    payData.put("payUrl", adapay.get("code"));
                    payData.put("orderNumber", order.getOrderNumber());
                    payData.put("mercOrderNo", order.getMercOrderNo());
                }

                resp.put("code", ResultCode.SUCCESS.code());
                payData.put("channel", channel.getChannel());
                order.setTransNo((adapay.get("id").toString()));
                resp.put("payData", payData);
                return resp;


            } else if ("pending".equals(adapay.get("status"))) {
                resp.put("code", ResultCode.FAIL.code());
                resp.put("msg", adapay.get("error_msg"));
                return resp;
            } else if ("failed".equals(adapay.get("status"))) {
                resp.put("code", ResultCode.FAIL.code());
                resp.put("msg", adapay.get("error_msg"));
                return resp;
            }

        } catch (Exception e) {
            log.error("adapay支付指令调用失败", e);
            e.printStackTrace();
        }
        return resp;
    }

    @Override
    public JSONObject tradePay(MerChantOrderDTO merchantOrderDTO, MerchantOrder order) {


        JSONObject obj = new JSONObject(6);

        String account_type = "WECHAT";
        if (StringUtil.isNotEmpty(order.getScanType()) && "01".equals(order.getScanType())) {
            account_type = "wechatPay".equals(order.getPayTypeCode()) ? "WECHAT" : "aliPay".equals(order.getPayTypeCode()) ? "ALIPAY" : "UQRCODEPAY";
        } else {
            account_type = "wechatPay".equals(order.getPayTypeCode()) ? "WECHAT" : "aliPay".equals(order.getPayTypeCode()) ? "ALIPAY" : "UQRCODEPAY";
        }

        String transType = account_type.equals("WECHAT") ? "wx_scan" : account_type.equals("ALIPAY") ? "alipay_scan" : "union_qr";

        Map<String, Object> paymentParams = new HashMap<>();
        Map<String, String> deviceInfo = new HashMap<>();
        Map expendParams = new HashMap();
        expendParams.put("auth_code", merchantOrderDTO.getAuthCode());

//        if("wx_lite".equals(transType)){
//            expendParams.put("auth_code",order.getMercUserId());
////            expendParams.put("wx_app_id",order.getAppletsAppid());
//        }else {
//            expendParams.put("buyer_id",order.getMercUserId());
//        }


        MmerchantHfInfo hfInfo = merchantHfInfoMapper.selectByMerchantCode(order.getMerchantCode());
        MsgException.checkNull(hfInfo, "商户进件信息不存在");


        Boolean flag = false;
        if ("3".equals(hfInfo.getStatus()) || "4".equals(hfInfo.getStatus())) {
            flag = true;
        }

        if (!flag) {
            MsgException.check(true, "商户信息不完整");
        }

        String order_amt = changeY2F(order.getConsumeFee());

        deviceInfo.put("device_ip", order.getIp());

        paymentParams.put("app_id", hfInfo.getApp_id());
        paymentParams.put("order_no", order.getOrderNumber());
        paymentParams.put("pay_channel", transType);
        paymentParams.put("pay_amt", order_amt);
        paymentParams.put("goods_title", "付款码收款");
        paymentParams.put("goods_desc", "付款码收款");
        paymentParams.put("device_info", deviceInfo);
        //异步通知地址，url为http/https路径，服务器POST回调，URL 上请勿附带参数
        paymentParams.put("notify_url", callBack);
        paymentParams.put("expend", expendParams);

        log.info(paymentParams.toString());
        JSONObject resp = new JSONObject();

        Map<String, Object> adapay = null;
        JSONObject payData = new JSONObject();
        try {

            this.init(hfInfo.getLive_api_key(), hfInfo.getTest_api_key(), hfInfo.getPriv_key());
            adapay = Payment.create(paymentParams);
            log.info("payment result=" + JSON.toJSONString(adapay));
            if ("succeeded".equals(adapay.get("status"))) {
                JSONObject object = JSON.parseObject(adapay.toString());
                if (object.containsKey("code") && "BBS10000".equals(object.get("code"))) {
                    obj.put("code", ResultCode.TRANSUNKNOW.code());
                    obj.put("msg", "用户支付中");
                    obj.put("channelOrderNo", object.getJSONObject("resp_data").get("trade_no"));
                    obj.put("transNo", object.getJSONObject("resp_data").get("log_no"));
                    obj.put("payStatus", "7");
                    return obj;
                } else if (object.containsKey("code") && "BBS00000".equals(object.get("code"))) {
                    obj.put("code", ResultCode.SUCCESS.code());
                    obj.put("msg", "成功");
                    obj.put("channelOrderNo", object.getJSONObject("resp_data").get("trade_no"));
                    obj.put("transNo", object.getJSONObject("resp_data").get("log_no"));
                    obj.put("payStatus", "1");
                    obj.put("payTime", DateUtils.convertDate(object.getJSONObject("resp_data").getString("trade_time")));
                    return obj;
                } else {
                    obj.put("code", ResultCode.FAIL.code());
                    obj.put("msg", object.get("error_msg"));
                    return obj;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        obj.put("code", ResultCode.FAIL.code());
        obj.put("msg", "失败");
        return obj;

    }

    @Override
    public Map<String, Object> refundPay(MerchantOrder order, String mchNo) {


        MmerchantHfInfo hfInfo = merchantHfInfoMapper.selectByMerchantCode(order.getMerchantCode());
        MsgException.checkNull(hfInfo, "商户进件信息不存在");


        Boolean flag = false;
        if ("3".equals(hfInfo.getStatus()) || "4".equals(hfInfo.getStatus())) {
            flag = true;
        }

        if (!flag) {
            MsgException.check(true, "商户信息不完整");
        }

        String order_amt = changeY2F(order.getConsumeFee());
        Map<String, Object> refundParams = new HashMap<String, Object>();
        String refundNo = "HF_refund_order_" + SnowFlakeUtil.nextId();
        refundParams.put("refund_amt", order_amt);
        refundParams.put("refund_order_no", refundNo);
        refundParams.put("notify_url", callBack);
        Map<String, Object> adapay = null;
        Map<String, Object> result = new HashMap<>(4);
        result.put("refundNo", refundNo);
        result.put("status", "3");
        result.put("code", ResultCode.FAIL.code());
        try {
            init(hfInfo.getLive_api_key(), hfInfo.getTest_api_key(), hfInfo.getPriv_key());

            log.info("request:{}",refundParams.toString());
            adapay = Refund.create(order.getTransNo(), refundParams);
            log.info("payment result=" + JSON.toJSONString(adapay));
            if ("pending".equals(adapay.get("status"))) {
                result.put("msg", "退款中！");
                result.put("data", adapay.get("id"));
                result.put("status", "4");
                result.put("code", ResultCode.SUCCESS.code());
                return result;
            } else if ("failed".equals(adapay.get("status"))) {
                result.put("msg", adapay.get("error_msg"));
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
        result.put("msg", "退款失败！");
        return result;


    }

    @Override
    public JSONObject tradeQuery(MerchantOrder order, String mchId) {
        return null;
    }

    @Override
    public JSONObject refundQuery(MerchantRefundOrder refundOrder) {
        return null;
    }

    @Override
    public Map<String, Object> closeOrder(String orderNumber, String channelNo) {
        return null;
    }

    @Override
    public Map<String, Object> getWxOpenId(MemberScanPayDTO memberScanPayDTO, MerchantChannelStatus channel) throws Exception {
        return null;
    }

    @Override
    public Map<String, Object> getUnionInfo(String userAuthCode, String paymentApp, String merchantId) throws Exception {

        MmerchantHfInfo hfInfo = merchantHfInfoMapper.selectByMerchantCode(merchantId);
        MsgException.checkNull(hfInfo, "商户进件信息不存在");

        Boolean flag = false;
        if ("3".equals(hfInfo.getStatus()) || "4".equals(hfInfo.getStatus())) {
            flag = true;
        }

        if (!flag) {
            MsgException.check(true, "商户信息不完整");
        }


        Map<String, Object> wxParam = new HashMap<String, Object>(4);
        wxParam.put("order_no", "query".equals(SnowFlakeUtil.nextId().toString()));
        wxParam.put("app_id", hfInfo.getApp_id());
        wxParam.put("auth_code", userAuthCode);
        Map<String, Object> result = AdapayCommon.queryAdapay(wxParam, "yifuyun");
        if (ObjectUtil.isNotEmpty(result) && result.containsKey("data")) {
            JSONObject object = JSON.parseObject(result.get("data").toString());
            if (ObjectUtil.isNotEmpty(object) && "succeeded".equals(object.getString("status"))) {
                JSONObject reqData = new JSONObject(2);
                reqData.put("data", object.getString("open_id"));
                reqData.put("userAuthCode", userAuthCode);
                reqData.put("appUpIdentifier", paymentApp);
                result.put("data", reqData);
                result.put("code", "1");
                result.put("msg", "获取成功");
            }

        }
        result.put("code", "0");
        result.put("msg", "获取失败");
        return result;
    }

    @Override
    public Object payNotifyCallBack(Map<String, String> params) {


        Map<String, String> result = new HashMap<>(2);
        result.put("code", "fail");
        result.put("msg", "失败");
        String type = params.get("type");

        switch (type) {
            case "payment.succeeded":
                Map data = JSON.parseObject(params.get("data"), Map.class);

                String orderNo = data.get("order_no").toString();
                QueryWrapper<MerchantOrder> queryWrapper = new QueryWrapper<MerchantOrder>().eq("orderNumber", orderNo);

                MerchantOrder order = merchantOrderService.getOne(queryWrapper);
                if (order == null) {
                    log.error("====================>【汇付】支付成功回调订单号查询，查询的订单为空：订单号：{}<====================", orderNo);
                    return YsConfig.RESULT_SUCCESS_CODE;
                }
                Date payDate = DateUtils.convertDateByString(data.get("created_time").toString());
                order.setTransDt(payDate);
                order.setTransNo(data.get("id").toString());
                order.setThirdTransNo(data.get("id").toString());
                merchantOrderService.updateOrderAndCreateProfit(order);
                result.put("code", "success");
                result.put("msg", "成功");

                break;
            case "payment.failed":
                data = JSON.parseObject(params.get("data"), Map.class);

                orderNo = data.get("order_no").toString();
                queryWrapper = new QueryWrapper<MerchantOrder>().eq("orderNumber", orderNo);

                order = merchantOrderService.getOne(queryWrapper);
                if (order == null) {
                    log.error("====================>【汇付】支付成功回调订单号查询，查询的订单为空：订单号：{}<====================", orderNo);
                    return YsConfig.RESULT_SUCCESS_CODE;
                }
                 payDate = DateUtils.convertDateByString(data.get("created_time").toString());
                order.setTransDt(payDate);
                order.setStatus("0");
                order.setTransNo(data.get("id").toString());
                order.setThirdTransNo(data.get("id").toString());
                merchantOrderService.update(order,queryWrapper);
                result.put("code", "success");
                result.put("msg", "成功");

                break;
            case "payment.close.succeeded":
                break;
            case "payment.close.failed":
                break;
            case "refund.succeeded":

                data = JSON.parseObject(params.get("data"), Map.class);

                String returnOrderNo = data.get("refund_order_no").toString();
                QueryWrapper<MerchantRefundOrder> returnQueryWrapper = new QueryWrapper<MerchantRefundOrder>().eq("refundNo", returnOrderNo);

               MerchantRefundOrder refundOrder = refundOrderService.getOne(returnQueryWrapper);
                if (refundOrder == null) {
                    log.error("====================>【汇付】支付成功回调订单号查询，查询的订单为空：订单号：{}<====================", returnOrderNo);
                    return YsConfig.RESULT_SUCCESS_CODE;
                }

                refundOrder.setStatus("1");
                refundOrderService.update(refundOrder,returnQueryWrapper);
                queryWrapper=new QueryWrapper<MerchantOrder>().eq("orderNumber",refundOrder.getOrderNumber());
                order=merchantOrderService.getOne(queryWrapper);

                order.setStatus("2");
                merchantOrderService.update(order,queryWrapper);

                break;
            case "refund.failed":

                data = JSON.parseObject(params.get("data"), Map.class);

                 returnOrderNo = data.get("refund_order_no").toString();
                returnQueryWrapper = new QueryWrapper<MerchantRefundOrder>().eq("refundNo", returnOrderNo);

                refundOrder = refundOrderService.getOne(returnQueryWrapper);
                if (refundOrder == null) {
                    log.error("====================>【汇付】支付成功回调订单号查询，查询的订单为空：订单号：{}<====================", returnOrderNo);
                    return YsConfig.RESULT_SUCCESS_CODE;
                }

                refundOrder.setStatus("3");
                refundOrderService.update(refundOrder,returnQueryWrapper);
                queryWrapper=new QueryWrapper<MerchantOrder>().eq("orderNumber",refundOrder.getOrderNumber());
                order=merchantOrderService.getOne(queryWrapper);

                order.setStatus("3");
                merchantOrderService.update(order,queryWrapper);
                break;
        }
        return result;
    }

    @Override
    public String tradePayWap(MerchantOrder order, MerchantChannelStatus channel) {
        return null;
    }

    @Override
    public JSONObject getUnionAccountUrl(JSONObject reqData) {
        return null;
    }

    @Override
    public JSONObject jftPay(JftReceiptOrder order, JftMercBaseInfo jftMerc, JftMercPaymentChannel jftChannel) {
        return null;
    }
}
