package com.bohuikeji.delivery.backstage.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipayTradePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bohuikeji.delivery.backstage.constants.KeyConst;
import com.bohuikeji.delivery.backstage.constants.payConst;
import com.bohuikeji.delivery.backstage.entity.*;
import com.bohuikeji.delivery.backstage.entity.socket.AdminNotice;
import com.bohuikeji.delivery.backstage.entity.vo.CourierAddressVo;
import com.bohuikeji.delivery.backstage.entity.wx.TWxUser;
import com.bohuikeji.delivery.backstage.listener.order.OrderAliCenterListener;
import com.bohuikeji.delivery.backstage.listener.order.OrderCreateListener;
import com.bohuikeji.delivery.backstage.listener.order.OrderDelayCancelListener;
import com.bohuikeji.delivery.backstage.listener.pay.PayTimoutListener;
import com.bohuikeji.delivery.backstage.listener.pay.TpsPayListener;
import com.bohuikeji.delivery.backstage.mapper.TPayMapper;
import com.bohuikeji.delivery.backstage.pay.AliPay;
import com.bohuikeji.delivery.backstage.pay.AliPayV2;
import com.bohuikeji.delivery.backstage.pay.PayServices;
import com.bohuikeji.delivery.backstage.service.*;
import com.bohuikeji.delivery.backstage.service.third.ThirdUtils;
import com.bohuikeji.delivery.backstage.task.CourierNoticeTask;
import com.bohuikeji.delivery.backstage.util.maiyatian.maltUtils;
import com.bohuikeji.frame.module.admin.base.ServiceImplBase;
import com.bohuikeji.frame.module.admin.component.MqTool;
import com.bohuikeji.frame.module.admin.component.RedisUtil;
import com.bohuikeji.frame.module.admin.entity.back.APIEntity;
import com.bohuikeji.frame.module.admin.entity.sys.SysError;
import com.bohuikeji.frame.module.admin.entity.sys.SysRes;
import com.bohuikeji.frame.module.admin.entity.vo.AliReturnPayVo;
import com.bohuikeji.frame.module.admin.utils.*;
import com.bohuikeji.frame.module.admin.utils.wx.wxPayUtil;
import com.bohuikeji.frame.module.admin.wxpay.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 支付交易信息表 服务实现类
 * </p>
 *
 * @author 10552
 * @since 2019-12-27
 */
@Service
@Slf4j
public class TPayServiceImpl extends ServiceImplBase<TPayMapper, TPay> implements ITPayService {

    @Autowired
    ITOrderService orderService;
    @Autowired
    ITPayService payService;
    @Autowired
    ITCourierService courierService;
    @Autowired
    ITDiscountOrderService orderDiscountService;
    @Autowired
    ITDiscountRecordService discountRecordService;
    @Autowired
    ITSettleService settleService;
    @Autowired
    ITDiscountMallService createVoucherService;
    @Autowired
    ITCustomerService customerService;
    @Autowired
    ITLogisticsService logisticsService;
    @Autowired
    MqTool mqTool;
    @Autowired
    ITNewsService newsService;
    @Autowired
    ITRefundService refundService;
    @Autowired
    ITCustomerWalletService customerWalletService;
    @Autowired
    ITwalletDetailService twalletDetailService;
    @Autowired
    ITGiveDetailService giveDetailService;
    @Autowired
    IWxUserService wxUserService;
    @Autowired
    CourierNoticeTask noticeTask;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    IGmsService gmsService;
    @Autowired
    ISocketService socketService;
    @Autowired
    ThirdUtils thirdUtils;
    @Autowired
    ITMaltFieldService maltFieldService;

    @Override
    public TPay getByNum(String payNum) {
        return this.getOne(new QueryWrapper<TPay>().eq("pay_num",payNum));
    }


    /**
     * 订单业务创建预支付单（微信，支付宝）
     * @return
     */
    @Override
    public TPay createBeforePay(TOrder order,String scenario,String payMethod,String payWay) {
        TPay pay=new TPay();
        pay.setPayStatus("待付款");
        pay.setPlayerId(order.getPlayerId());
        pay.setPayNum(NumberUtils.get("C"));
        pay.setMerchantNum(order.getOrderNum());
        pay.setOrderId(order.getOrderId());
        pay.setCreateTime(LocalDateTime.now());
        pay.setPayScenario(scenario);
        pay.setPayMethod(payMethod);
        pay.setPayWay(payWay);
        if("订单小费".equals(scenario)){
            pay.setPayExpectPrice(order.getTipAmount());
        }else {
            pay.setPayExpectPrice(order.getOrderExpectPrice());
        }
        this.save(pay);
        mqTool.sendDelayMsg(pay.getPayNum(), PayTimoutListener.class, Duration.ofHours(3));
        return pay;
    }


    /**
     * 微信&支付宝，扫码支付预支付订单修改
     * @param pay
     * @param tOrder
     * @param request
     * @return
     */
    @Override
    public boolean wxAlipay(TPay pay, TOrder tOrder, HttpServletRequest request) {
        if(pay.getPayChannel().equals("微信")){
            if("待付款".equals(pay.getPayStatus())){
                wxPayUtil payUtil = new wxPayUtil();
                //发起支付请求
                Map<String, String> rs = payUtil.sweepOrder(pay.getPayNum(), tOrder.getOrderFactPrice().toString(),"订单补充支付", IpUtil.getIpAddr(request), tOrder.getPayWay());
                if("FAIL".equals(rs.get("result_code"))){
                    log.error("微信支付失败：[{}]",rs);
                    return false;
                }
                payService.wxUpdatePay(rs,tOrder,"补充支付",rs.get("out_trade_no"));
                return true;
            }
        }
        if(pay.getPayChannel().equals("支付宝")){
            if("待付款".equals(pay.getPayStatus())){
                //发起支付请求
                AlipayTradePayResponse response = AliPay.alipaycode(tOrder.getPayWay(),pay.getPayNum(),tOrder.getOrderFactPrice().toString(),"同城急送");
                return response == null?false:true;
            }
        }
        return false;
    }

    /**
     * 微信扫码支付回调，需要在支付成功后，直接进行业务处理
     * @param rs
     * @param order
     * @param payScenario
     * @param payNum
     * @return
     */
    @Override
    public TPay wxUpdatePay(Map<String, String> rs, TOrder order, String payScenario, String payNum) {
        TPay pay = payService.getOne(new QueryWrapper<TPay>().eq("pay_num",payNum));
        pay.setPayFactPrice((WXPayUtil.FenToDecimal(rs.get("total_fee"))));//获取微信支付金额由分转成元/真鸡儿啰嗦
        pay.setPayChannel("微信");
        pay.setPayChannelNum(rs.get("transaction_id"));
        pay.setPayStatus("已支付");
        pay.setPayScenario(payScenario);
        pay.setPayTime(LocalDateTime.now());
        if(payService.updateById(pay)){
            /**
             * 当支付完成之后，订单状态是待取件则自动完成取件
             */
            //寄付
            if("取件中".equals(order.getOrderStatus())){
                order.setOrderStatus("待派送");
                order.setConfirmPickTime(LocalDateTime.now());
                TOrderCircu.insertCircu(order);
                log.info("订单：[{}]自动取件完成",order.getOrderNum());
            }
            //寄付----需要计算时间支付的金额
            if("补充支付".equals(payScenario)){
                TOrder tOrder = orderService.getById(order.getOrderId());
                order.setOrderFactPrice(tOrder.getOrderFactPrice().add(pay.getPayFactPrice()));
            }
            order.setOrderExpectPrice(order.getOrderFactPrice());
            order.setTotalOrderAmount(order.getOrderFactPrice());//订单总额
            //计算佣金
            orderService.updateById(orderService.extractExtract(order));
        }else {
            log.error("订单交易信息添加失败！ "+rs);
            return pay;
        }
        log.info("通知栏消息："+pay);
        pay.setPayExpectPrice(order.getOrderExpectPrice());
        pay.setOrderId(order.getOrderId());
        payService.updateById(pay);//更新支付记录种订单id
        return pay;
    }

    @Override
    public TPay callbackPayServis(JSONObject jsonObject, AliReturnPayVo req, TPay pay) {
        TOrder order;
        if("客户支付".equals(pay.getPayMethod())){
            order=redisUtil.get("order:create:num:"+pay.getMerchantNum(),TOrder.class);
            if(order==null){
                order=orderService.getByNum(pay.getMerchantNum());
            }
            log.info("下单支付回调时走这里{},",order.getOrderFactPrice());
        }else {
            order=orderService.getByNum(pay.getMerchantNum());
            log.info("其他支付回调时走这里{},",order.getOrderFactPrice());
        }
        payService.updateById(PayServices.orderPaySrevice(jsonObject,req,pay));
        TOrder tOrder = this.saveOrder(order,pay);
        if(jsonObject != null && StringUtils.isNotBlank(jsonObject.getString("promotion_detail"))){
            orderDiscountService.wxDiscount(tOrder,jsonObject);
        }
        //pay.setPayExpectPrice(tOrder.getOrderExpectPrice());
        pay.setOrderId(tOrder.getOrderId());
        payService.updateById(pay);//更新支付记录种订单id
        if("抖音".equals(pay.getPayWay())){
            settleService.saveSeettle(pay);
        }
        if("快手".equals(pay.getPayWay())){
            settleService.saveSeettle(pay);
        }
        redisUtil.del("order:create:num:"+pay.getMerchantNum());//下单支付完成后删除缓存种的数据
        log.info("支付记录信息："+pay);
        return pay;
    }

    /**
     * 钱包支付业务处理
     * @param pay
     * @param tCustomerWallet
     * @param order
     * @return
     */
    @Override
    public TPay walletPay(TPay pay, TCustomerWallet tCustomerWallet,TOrder order) {
        log.info("进入钱包支付业务处理");
        TOrder tOrder=null;
        if(payService.updateById(PayServices.orderPaySrevice(null,null,pay))){
            if (order!=null){
                tOrder = this.saveOrder(order,pay);
                if(customerWalletService.updateById(tCustomerWallet.setWalletPrice(tCustomerWallet.getWalletPrice().subtract(tOrder.getOrderFactPrice())))){
                    SysRes res=new SysRes();
                    Object giftSum=res.sql().selectObj("select IFNULL(sum(gift_amount),0) as sumc from t_give_detail where customer_id={0} and give_status='未使用'",tCustomerWallet.getCustomerId());//订单预结算金额
                    if(tCustomerWallet.getWalletPrice().compareTo(new BigDecimal(giftSum.toString())) <1){
                        List<TGiveDetail> giveDetails = giveDetailService.list(new QueryWrapper<TGiveDetail>().eq("give_status","未使用").eq("customer_id",tCustomerWallet.getCustomerId()));
                        for(TGiveDetail giveDetail : giveDetails){
                            giveDetail.setGiveStatus("已使用");
                            giveDetail.setUpdateTime(LocalDateTime.now());
                            giveDetailService.updateById(giveDetail);
                        }
                    }
                    twalletDetailService.saveDetail(null,pay,null,tCustomerWallet,"订单支付");
                }
            }
        }
        pay.setOrderId(tOrder.getOrderId());
        payService.updateById(pay);//更新支付记录种订单id
        log.info("支付记录信息："+pay);
        return pay;
    }


    /**
     * 订单业务、补充支付信息处理
     * @param order
     * @param pay
     */
    private TOrder saveOrder(TOrder order,TPay pay){
        if("业务支付".equals(pay.getPayScenario())){
            log.info("@@@@@@@@@业务支付开始日志@@@@@@@@@");
            //支付成功计算佣金
            order.setOrderStatus("待接单");
            order.setOrderActualPrice(pay.getActualPrice());//订单最终实际收入
            order.setOrderFactPrice(order.getOrderFactPrice().add(pay.getActualPrice()));
            order.setPrefAmount(order.getOrderFactPrice().subtract(order.getOrderActualPrice()).add(order.getPrefAmount()));
            order = orderService.extractExtract(order);//三方结算
            orderService.save(order);
            discountRecordService.updateRecord(order);//下单成功后保存优惠使用记录
            if("麦芽田".equals(order.getOrderChannel())){
                TMaltField maltField = maltFieldService.getOne(new QueryWrapper<TMaltField>().eq("shop_id",order.getShopId()));
                maltUtils.getDeliveryChange(order,null,maltField,null,"",1);
            }
            ///发送订单创建完成通知
            mqTool.sendMsg(order.getOrderNum(), OrderCreateListener.class);
            //将所有订单推送给付总
            //newsService.pushCourierMsg1(59,"新订单通知","派送员您好，有从：{0}，送往：{1}新的订单：{2}未领取，请到配送大厅查看。",order.getMailingAddress().getAddress(),order.getReceiptAddress().getAddress(),order.getOrderNum());
            //推送消息通知
            TaskUtils.run(noticeTask).addParam(CourierNoticeTask.KEY_ORDER_ID,order.getOrderId());
            //只有今天下的单可以进入自动取消队列
            /*if("今天".equals(order.getPickTime().substring(0,order.getPickTime().indexOf("/")))){
                long minutes = ChronoUnit.MINUTES.between(LocalDateTime.now(), order.getSurplusPickTime());
                //设置订单延时(订单自动超时)操作
                mqTool.sendDelayMsg(order.getOrderNum(), OrderDelayCancelListener.class,Duration.ofMinutes(minutes));
            }*/
            mqTool.sendMsg(order.getOrderNum(), OrderAliCenterListener.class);
            long minutes = ChronoUnit.MINUTES.between(LocalDateTime.now(), order.getSurplusPickTime());
            //设置订单延时(订单自动超时)操作
            mqTool.sendDelayMsg(order.getOrderNum(), OrderDelayCancelListener.class,Duration.ofMinutes(minutes));
            //累计客户的下单次数
            TCustomer tCustomer = customerService.getOne(new QueryWrapper<TCustomer>().eq("customer_id",order.getPlayerId()));
            customerService.updateById(tCustomer.setOrderFrequency(tCustomer.getOrderFrequency()+1));
        }
        //订单寄付状态下，支付宝才能在“取件中”状态下进行扫码补付、或是派送员代缴补付，补付结束后计算实际支付金额后在进行三方结算。注意：只有寄付模式下才能在取件中状态进行补付
        if("第三方补充支付".equals(pay.getPayScenario())){
            log.info("@@@@@@@@@第三方补充支付开始日志@@@@@@@@@");
            //第一次支付和第二次补付之和
            order.setOrderFactPrice(order.getOrderFactPrice().add(pay.getPayFactPrice()));
            order.setOrderActualPrice(order.getOrderActualPrice().add(pay.getActualPrice()));
            order.setOrderExpectPrice(order.getOrderFactPrice());
            //订单总额
            order.setTotalOrderAmount(order.getOrderFactPrice());
            //三方结算
            orderService.updateById(order);
            TOrderCircu.insertCircu(order);
            mqTool.sendMsg(order.getOrderNum(), TpsPayListener.class);
            log.info("@@@@@@@@@第三方补充支付结束日志@@@@@@@@@：{},[{}-{}],补付金额：{}",order.getOrderNum(),order.getMailingName(),order.getReceiptName(),pay.getPayFactPrice());
        }
        if("补充支付".equals(pay.getPayScenario())){
            log.info("@@@@@@@@@补充支付开始日志@@@@@@@@@");
            if("骑手代付".equals(pay.getPayMethod())){
                order.setOrderStatus("待派送");
            }else{
                AdminNotice notice = new AdminNotice(StringUtils.formatStr("您好，来自{0}的客户{1}，修改了订单：{2}的地址，请及时处理！", order.getMailingAddress().getProvince() + order.getMailingAddress().getCity(),order.getMailingName(),order.getOrderNum()));
                socketService.sendAdminMsg(notice.setFranId(order.getFranId()));
                Map<String,Object> params=new HashMap<>(1);
                params.put("user",order.getMailingName());
                params.put("order",order.getOrderNum());
                params.put("mag",order.getMailingAddress().toString());
                params.put("rep",order.getReceiptAddress().toString());
                YiXunGmsUtils.sendMsg("18347923617","SMS_TEMP_ADDRESS_EDIT",params);
            }
            order.setOrderFactPrice(order.getOrderFactPrice().add(pay.getPayFactPrice()));//第一次支付和第二次补付之和
            order.setOrderActualPrice(order.getOrderActualPrice().add(pay.getActualPrice()));
            order.setOrderExpectPrice(order.getOrderFactPrice());
            order.setTotalOrderAmount(order.getOrderFactPrice());//订单总额
            order.setConfirmPickTime(LocalDateTime.now());//取件时间
            if(order.getCourierId()!=null){
                orderService.updateById(orderService.extractExtract(order));//三方结算
            }else {
                orderService.updateById(order);//三方结算
            }
            TOrderCircu.insertCircu(order);
        }
        if("订单小费".equals(pay.getPayScenario())){
            log.info("@@@@@@@@@订单添加小费@@@@@@@@@");
            order.setOrderFactPrice(order.getOrderFactPrice().add(pay.getPayFactPrice()));//在原基础上加上小费金额
            order.setOrderActualPrice(order.getOrderActualPrice().add(pay.getActualPrice()));//在原实际金额上加小费的实际金额
            order.setOrderExpectPrice(order.getOrderFactPrice());
            order.setTotalOrderAmount(order.getOrderFactPrice());//订单总额
            order.setTipAmount(order.getTipAmount().add(pay.getPayFactPrice()));
            order.setOrderCourierMoney(order.getOrderCourierMoney().add(pay.getPayFactPrice()));
            orderService.updateById(order);
            thirdUtils.addOrderTip(order,pay.getPayFactPrice());
            socketService.sendAdminMsg(new AdminNotice(StringUtils.formatStr("您好，来自{0}的订单已支付小费，请催促骑手接单！",
                    order.getMailingAddress().getProvince() + order.getMailingAddress().getCity()))
                    .setType("warning").setFranId(order.getFranId()));
        }
        return order;
    }

    @Override
    public APIEntity getPayAPIEntity(TOrder tOrder, HttpServletRequest request) throws Exception {
        TCustomer customer = customerService.getById(tOrder.getPlayerId());
        String openId = null;
        //创建预支付订单
        TPay pay  =payService.createBeforePay(tOrder,tOrder.getServiceType(),"客户支付",payConst.getway(tOrder.getType()));
        BigDecimal orderPrice  = new BigDecimal("0.00").setScale(2, BigDecimal.ROUND_DOWN);
        if("业务支付".equals(tOrder.getServiceType())){
            orderPrice = tOrder.getOrderExpectPrice();
            log.info("@@@@@@@@@@@@@@@@@@#$#################业务支付金额:{}",orderPrice);
        }
        if("补充支付".equals(tOrder.getServiceType())){
            orderPrice = tOrder.getOrderExpectPrice().subtract(tOrder.getOrderFactPrice());
            log.info("@@@@@@@@@@@@@@@@@@#$#################补充支付金额:{}",orderPrice);
        }
        if("WALLET".equals(tOrder.getType())){
            TCustomerWallet tCustomerWallet = customerWalletService.getOne(new QueryWrapper<TCustomerWallet>().eq("customer_id",tOrder.getPlayerId()));
            if(tCustomerWallet != null && tCustomerWallet.getWalletPrice().compareTo(tOrder.getOrderExpectPrice()) > -1){
                pay =payService.createBeforePay(tOrder,"业务支付","客户支付","钱包");
                payService.walletPay(pay,tCustomerWallet,tOrder);
                orderService.post(pay.getOrderId(), "该订单已从钱包扣款。");//向客户推送订阅消息
                redisUtil.del("order:create:num:"+tOrder.getOrderNum());//钱包支付时直接存入数据库，删除缓存中订单信息。
                mqTool.sendMsg(tOrder.getOrderNum(), OrderAliCenterListener.class);
                return APIEntity.success(tOrder);
            }else {
                return APIEntity.fail("钱包金额不足下单失败，请选择其他支付方式。");
            }
        }
        if("JSAPI".equals(tOrder.getType())){
            openId = customer.getOpenId();
        }
        if("aliClient".equals(tOrder.getType())){
            TWxUser wxUser = wxUserService.getOne(new QueryWrapper<TWxUser>().eq("user_id",customer.getCustomerId()).eq("wx_app_type","ALICLIENT"));
            if(wxUser == null){
                return APIEntity.fail("请用户授权");
            }
            openId = wxUser.getWxUserOpenid();
        }
        if("kuaiShou".equals(tOrder.getType())){
            TWxUser wxUser = wxUserService.getOne(new QueryWrapper<TWxUser>().eq("user_id",customer.getCustomerId()).eq("wx_app_type","KUAISHOU"));
            if(wxUser == null){
                return APIEntity.fail("请用户授权");
            }
            openId = wxUser.getWxUserOpenid();
        }
        JSONObject object = null;
        String payNum = pay.getPayNum();
        String[] centralChina={"同城急送","官方平台","急送平台"};
        if(Arrays.asList(centralChina).contains(tOrder.getOrderChannel())){
            TWxUser wxUser = wxUserService.getOne(new QueryWrapper<TWxUser>().eq("user_id",customer.getCustomerId()).eq("wx_app_name",tOrder.getOrderChannel()).eq("wx_app_type","ALICLIENT"));
            if(wxUser == null){
                return APIEntity.fail("请用户授权");
            }
            log.error("下单支付渠道类型：{}",tOrder.getOrderChannel());
            if("同城急送".equals(tOrder.getOrderChannel())){
                object = payConst.getAliObject(tOrder.getType(),tOrder.getOrderChannel(),payNum,wxUser.getWxUserOpenid(),orderPrice,request);
            }
            if("官方平台".equals(tOrder.getOrderChannel())){
                object = payConst.getAliObject(tOrder.getType(),tOrder.getOrderChannel(),payNum,openId,orderPrice,request);
            }
            if("急送平台".equals(tOrder.getOrderChannel())){
                object = payConst.getAliObject(tOrder.getType(),tOrder.getOrderChannel(),payNum,openId,orderPrice,request);
            }
        }else {
            object = payConst.getObject(tOrder.getType(),payNum,openId,orderPrice,request);
        }
        if(object==null){
            SysError.saveError("[客户下单未调起支付]，下单渠道：{0}",tOrder.getOrderChannel());
        }
        return object==null?APIEntity.fail("客户调起"+payConst.getway(tOrder.getType())+"支付错误"):APIEntity.success(object);
    }

    @Override
    public TPay lastWaitPay(Integer orderId) {
        return getOne(new QueryWrapper<TPay>().eq("order_id",orderId).eq("pay_status", "待付款").orderByDesc("pay_id").last(" limit 1"),false);
    }
}
