package com.ruoyi.frequency.rechargeorder.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.DictConstant;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.RechargeOrderReq;
import com.ruoyi.enums.PlatformRecordEnums;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.givewallerecord.service.GiveWalletRecordService;
import com.ruoyi.frequency.onlinerecord.service.OnlineRecordService;
import com.ruoyi.frequency.platformrecord.service.PlatformRecordService;
import com.ruoyi.frequency.rechargecoin.entity.RechargeCoin;
import com.ruoyi.frequency.rechargecoin.service.RechargeCoinService;
import com.ruoyi.frequency.rechargeorder.entity.RechargeOrder;
import com.ruoyi.frequency.rechargeorder.mapper.RechargeOrderMapper;
import com.ruoyi.frequency.rechargeorder.model.result.RechargeOrderCount;
import com.ruoyi.frequency.rechargeorder.service.RechargeOrderService;
import com.ruoyi.frequency.wallerecord.service.WalletRecordService;
import com.ruoyi.pay.enums.PayEnums;
import com.ruoyi.pay.enums.PaySourceEnums;
import com.ruoyi.pay.utils.AlipayCore;
import com.ruoyi.pay.utils.HttpRequestUtil;
import com.ruoyi.pay.utils.PayUtil;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.vo.UserInfo;
import com.ruoyi.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 充值余额订单Service业务层处理
 *
 * @author liwenlong
 * @date 2023-10-25
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class RechargeOrderServiceImpl extends ServiceImpl<RechargeOrderMapper, RechargeOrder> implements RechargeOrderService {
    @Autowired
    private RechargeOrderMapper rechargeOrderMapper;

    /**
     * 查询充值余额订单
     *
     * @param id 充值余额订单主键
     * @return 充值余额订单
     */
    @Override
    public RechargeOrder selectRechargeOrderById(Long id) {
        RechargeOrder rechargeOrder = rechargeOrderMapper.selectRechargeOrderById(id);

        if (rechargeOrder != null) {
            Set<UserVo> userVoSet = CollectionUtil.newHashSet(new UserVo(UserEnums.customer.getCode(), rechargeOrder.getCustomerId()));
            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, null);

            rechargeOrder.setUserInfo(userMap.get(new UserVo(UserEnums.customer.getCode(), rechargeOrder.getCustomerId())));
        }

        return rechargeOrder;
    }

    @Autowired
    private UserService userService;

    /**
     * 查询充值余额订单列表
     *
     * @param rechargeOrder 充值余额订单
     * @return 充值余额订单
     */
    @Override
    public List<RechargeOrder> selectRechargeOrderList(RechargeOrder rechargeOrder) {
        List<RechargeOrder> rechargeOrders = rechargeOrderList(rechargeOrder);

        if (rechargeOrders != null && rechargeOrders.size() > 0) {
            Set<UserVo> userVoSet = rechargeOrders.stream().map(s -> new UserVo(UserEnums.customer.getCode(), s.getCustomerId())).collect(Collectors.toSet());
            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, null);

            rechargeOrders.stream().forEach(s -> {
                s.setUserInfo(userMap.get(new UserVo(UserEnums.customer.getCode(), s.getCustomerId())));
            });
        }
        return rechargeOrders;
    }

    private List<RechargeOrder> rechargeOrderList(RechargeOrder rechargeOrder) {
        List<RechargeOrder> rechargeOrders = rechargeOrderMapper.selectRechargeOrderList(rechargeOrder);
        return rechargeOrders;
    }

    @Override
    public RechargeOrderCount statistics(RechargeOrder rechargeOrder) {
        List<RechargeOrder> rechargeOrders = rechargeOrderList(rechargeOrder);
        List<Long> rechargeOrderIdList = rechargeOrders.stream().map(x -> x.getId()).collect(Collectors.toList());
        rechargeOrderIdList.add(-1L);
        return rechargeOrderMapper.statistics(rechargeOrderIdList);
    }

    /**
     * 新增充值余额订单
     *
     * @param rechargeOrder 充值余额订单
     * @return 结果
     */
    @Override
    public int insertRechargeOrder(RechargeOrder rechargeOrder) {
        rechargeOrder.setCreateTime(DateUtils.getNowDate());
        return rechargeOrderMapper.insertRechargeOrder(rechargeOrder);
    }

    /**
     * 修改充值余额订单
     *
     * @param rechargeOrder 充值余额订单
     * @return 结果
     */
    @Override
    public int updateRechargeOrder(RechargeOrder rechargeOrder) {
        rechargeOrder.setUpdateTime(DateUtils.getNowDate());
        return rechargeOrderMapper.updateRechargeOrder(rechargeOrder);
    }

    /**
     * 批量删除充值余额订单
     *
     * @param ids 需要删除的充值余额订单主键
     * @return 结果
     */
    @Override
    public int deleteRechargeOrderByIds(Long[] ids) {
        this.lambdaUpdate().set(RechargeOrder::getDelFlag, PublicCommon.删除).in(RechargeOrder::getId, ids).update();
        return ids.length;
    }

    /**
     * 删除充值余额订单信息
     *
     * @param id 充值余额订单主键
     * @return 结果
     */
    @Override
    public int deleteRechargeOrderById(Long id) {
        this.lambdaUpdate().set(RechargeOrder::getDelFlag, PublicCommon.删除).eq(RechargeOrder::getId, id).update();
        return 1;
    }

    @Autowired
    private RechargeCoinService rechargeCoinService;

    @Autowired
    private PayUtil payUtil;

    @Override
    public ResponseData rechargeOrder(RechargeOrderReq req, UserVo userVo) {

        RechargeOrder rechargeOrder = new RechargeOrder();

        //分为两种情况 1使用充值包 2 自定义金额
        if (ObjectUtil.isNotEmpty(req.getRechargeCoinId())) {
            RechargeCoin rechargeCoin = rechargeCoinService.getById(req.getRechargeCoinId());
            rechargeOrder.setPayPrice(rechargeCoin.getPrice());
            rechargeOrder.setPrice(rechargeCoin.getPrice().add(rechargeCoin.getCoin()));
        } else {

            SysDictData 充值赠送金额比例 = businessUtil.getDict(DictConstant.充值赠送金额比例);

            BigDecimal ratio = BigDecimal.ZERO;
            if (充值赠送金额比例 != null) {
                ratio = new BigDecimal(充值赠送金额比例.getDictValue());
            }

            rechargeOrder.setPayPrice(req.getAmount());
            rechargeOrder.setPrice(req.getAmount().add(req.getAmount().multiply(ratio)));
        }
        rechargeOrder.setCustomerId(userVo.getUserId());
        rechargeOrder.setPayType(req.getPayType());
        rechargeOrder.setOrderNo(generateOrderNo());
        this.save(rechargeOrder);

        ResponseData responseData = payUtil.pay(userVo, rechargeOrder.getId(), req.getPayType(), rechargeOrder.getPayPrice(), BigDecimal.ZERO, rechargeOrder.getOrderNo(), PaySourceEnums.recharge_pay, WalletDetailEnums.ORDER_PAY);

        if (responseData.getSuccess() || responseData.getCode().equals(210)) {
            //支付后操作
            if (req.getPayType().equals(PayEnums.balance.getCode()) || req.getPayType().equals(PayEnums.apple.getCode())) {
                after(rechargeOrder);
            }
        }

        return responseData;

    }

    @Autowired
    private PlatformRecordService platformRecordService;

    /**
     * 支付后操作
     *
     * @param order
     */
    private void after(RechargeOrder order) {

        boolean update = this.lambdaUpdate().set(RechargeOrder::getPayStatus, PublicCommon.Pay.已支付)
                .eq(RechargeOrder::getPayStatus, PublicCommon.Pay.未支付)
                .eq(RechargeOrder::getId, order.getId()).update();

        if (update) {
            //充值余额
            walletRecordService.updateBalance(new UserVo(UserEnums.customer.getCode(), order.getCustomerId()), WalletDetailEnums.RECHARGE_BALANCE, order.getId(), order.getPayPrice(), PublicCommon.Wallet.可提现);

            //充值抵用金
            giveWalletRecordService.updateGiveBalance(new UserVo(UserEnums.customer.getCode(), order.getCustomerId()), WalletDetailEnums.RECHARGE_GIVE_BALANCE, order.getId(), order.getPrice().subtract(order.getPayPrice()), PublicCommon.Wallet.可提现);

            //平台流水
            platformRecordService.addPlatformRecord(new UserVo(UserEnums.customer.getCode(), order.getCustomerId()), order.getId(), order.getPrice(), PlatformRecordEnums.RECHARGE_BALANCE);

        }
    }

    @Autowired
    private GiveWalletRecordService giveWalletRecordService;

    /**
     * 生成订单号
     *
     * @return
     */
    private String generateOrderNo() {
        String orderNo;
        String prefix = "CZ";
        while (true) {
            orderNo = prefix + DateUtil.format(new Date(), "MMdd" + RandomUtil.randomNumbers(6));
            RechargeOrder old = this.getBaseMapper().selectOne(new QueryWrapper<RechargeOrder>().lambda()
                    .eq(RechargeOrder::getOrderNo, orderNo)

            );
            if (old == null) {
                break;
            }
        }
        return orderNo;
    }

    @Autowired
    private WalletRecordService walletRecordService;

    @Override
    public ResponseData rechargeAliNotify(HttpServletRequest request, HttpServletResponse response) {
        log.info("******************************进入支付宝支付回调");
        //接收参数进行校验
        Map<String, String> paramsMap = AlipayCore.updateMap(request);
        //流水号
        String payId = paramsMap.get("out_trade_no");
        // 支付宝订单号
        String orderNo = paramsMap.get("trade_no");
        //付款状态
        String tradeStatus = paramsMap.get("trade_status");
        log.info("******************************payId=" + payId);

        RechargeOrder cur = baseMapper.selectOne(new QueryWrapper<RechargeOrder>().lambda().eq(RechargeOrder::getOrderNo, payId));
        if (cur == null) {
            log.error("支付信息丢失");
            return ResponseData.error("支付信息丢失");
        }
        if (cur.getPayStatus() == 2) {
            log.error("支付宝回调已经开始 回去吧");
            return ResponseData.error("支付宝回调已经开始 回去吧");
        }
        if (cur.getPayStatus() == 3) {
            //退款
            ResponseData responseData = payUtil.refund(new UserVo(UserEnums.customer.getCode(), cur.getCustomerId()), cur.getId(), cur.getPayType(), cur.getPayPrice(), cur.getPrice(), cur.getOrderNo(), cur.getAliPayOrder(), BigDecimal.ZERO);
            if (!responseData.getSuccess()) {
                log.error("退款失败：" + cur.getOrderNo());
            }
            return responseData;
        }
        if ("TRADE_SUCCESS".equalsIgnoreCase(tradeStatus)) {

            this.lambdaUpdate().set(RechargeOrder::getAliPayOrder, orderNo).eq(RechargeOrder::getId, cur.getId()).update();

            after(cur);//支付后逻辑处理
            log.info("正常");
            return ResponseData.success();
        } else {
            cur.setPayStatus(3);
            baseMapper.updateById(cur);
            log.error("支付失败");
        }
        return ResponseData.error("");
    }

    @Override
    public ResponseData rechargeWxNotify(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String> requestMap = HttpRequestUtil.parseXml(request);
        System.out.println("requestMap:" + requestMap.toString());
        // 微信中的订单号
        String transactionId = requestMap.get("transaction_id");
        // 用户唯一标识
        String openid = requestMap.get("openid");
        //流水号
        String payId = requestMap.get("out_trade_no");

        RechargeOrder cur = baseMapper.selectOne(new QueryWrapper<RechargeOrder>().lambda().eq(RechargeOrder::getOrderNo, payId));
        if (cur == null) {
            log.error("支付信息丢失");
            return ResponseData.error("支付信息丢失");
        }
        if (cur.getPayStatus() == 2) {
            log.error("微信回调已经开始 回去吧");
            return ResponseData.error("支付宝回调已经开始 回去吧");
        }
        if (cur.getPayStatus() == 3) {
            //退款
            ResponseData responseData = payUtil.refund(new UserVo(UserEnums.customer.getCode(), cur.getCustomerId()), cur.getId(), cur.getPayType(), cur.getPayPrice(), cur.getPayPrice(), cur.getOrderNo(), cur.getAliPayOrder(), BigDecimal.ZERO);
            if (!responseData.getSuccess()) {
                log.error("退款失败：" + cur.getOrderNo());
            }
            return responseData;
        }

        if ("SUCCESS".equals(requestMap.get("result_code"))) {
            after(cur);//支付后逻辑处理
            log.info("正常");
            return ResponseData.success();
        } else {
            cur.setPayStatus(3);
            baseMapper.updateById(cur);
            log.error("支付失败");
        }

        return ResponseData.error("");
    }

    @Override
    public ResponseData rechargeLakalaNotify(Map<String, String> requestMap) {
        System.out.println("requestMap:" + requestMap.toString());
        //流水号
        String payId = requestMap.get("out_order_no");

        RechargeOrder cur = baseMapper.selectOne(new QueryWrapper<RechargeOrder>().lambda().eq(RechargeOrder::getOrderNo, payId));
        if (cur == null) {
            log.error("支付信息丢失");
            return ResponseData.error("支付信息丢失");
        }
        if (cur.getPayStatus() == 2) {
            log.error("拉卡拉回调已经开始 回去吧");
            return ResponseData.error("拉卡拉回调已经开始 回去吧");
        }
        if (cur.getPayStatus() == 3) {
            //退款
            ResponseData responseData = payUtil.refund(new UserVo(UserEnums.customer.getCode(), cur.getCustomerId()), cur.getId(), cur.getPayType(), cur.getPayPrice(), cur.getPayPrice(), cur.getOrderNo(), cur.getAliPayOrder(), BigDecimal.ZERO);
            if (!responseData.getSuccess()) {
                log.error("退款失败：" + cur.getOrderNo());
            }
            return responseData;
        }

        //order_status 聚合收银台订单状态 	0:待支付 1:支付中 2:支付成功 3:支付失败 4:已过期 5:已取消 6：部分退款或者全部退款
        if (("2").equals(requestMap.get("order_status"))) {
            after(cur);//支付后逻辑处理
            log.info("正常");

            //设置成功标识
            businessUtil.setOutTradeNo(payId);

            //添加支付记录
            onlineRecordService.addOnlineRecord(new UserVo(UserEnums.customer.getCode(), cur.getCustomerId()), cur.getId(), cur.getPayPrice(), WalletDetailEnums.RECHARGE_BALANCE);

            return ResponseData.success();
        } else {
            cur.setPayStatus(3);
            baseMapper.updateById(cur);
            log.error("支付失败");
        }

        return ResponseData.error("");
    }

    @Autowired
    private OnlineRecordService onlineRecordService;

    @Autowired
    private BusinessUtil businessUtil;
}
