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

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.page.PageResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.BondPayReq;
import com.ruoyi.controller.req.BondRecordPageReq;
import com.ruoyi.enums.PlatformRecordEnums;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.bondamounrecord.service.BondAmountRecordService;
import com.ruoyi.frequency.bondrecord.entity.BondRecord;
import com.ruoyi.frequency.bondrecord.mapper.BondRecordMapper;
import com.ruoyi.frequency.bondrecord.service.BondRecordService;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.onlinerecord.service.OnlineRecordService;
import com.ruoyi.frequency.platformrecord.service.PlatformRecordService;
import com.ruoyi.frequency.store.entity.Store;
import com.ruoyi.frequency.store.service.StoreService;
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.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;

/**
 * 保证金记录Service业务层处理
 *
 * @author liwenlong
 * @date 2023-10-18
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class BondRecordServiceImpl extends ServiceImpl<BondRecordMapper, BondRecord>  implements BondRecordService
{
    @Autowired
    private BondRecordMapper bondRecordMapper;

    /**
     * 查询保证金记录
     *
     * @param id 保证金记录主键
     * @return 保证金记录
     */
    @Override
    public BondRecord selectBondRecordById(Long id)
    {
        return bondRecordMapper.selectBondRecordById(id);
    }

    /**
     * 查询保证金记录列表
     *
     * @param bondRecord 保证金记录
     * @return 保证金记录
     */
    @Override
    public List<BondRecord> selectBondRecordList(BondRecord bondRecord)
    {
        return bondRecordMapper.selectBondRecordList(bondRecord);
    }

    /**
     * 新增保证金记录
     *
     * @param bondRecord 保证金记录
     * @return 结果
     */
    @Override
    public int insertBondRecord(BondRecord bondRecord)
    {
        return bondRecordMapper.insertBondRecord(bondRecord);
    }

    /**
     * 修改保证金记录
     *
     * @param bondRecord 保证金记录
     * @return 结果
     */
    @Override
    public int updateBondRecord(BondRecord bondRecord)
    {
        bondRecord.setUpdateTime(DateUtils.getNowDate());
        return bondRecordMapper.updateBondRecord(bondRecord);
    }

    /**
     * 批量删除保证金记录
     *
     * @param ids 需要删除的保证金记录主键
     * @return 结果
     */
    @Override
    public int deleteBondRecordByIds(Long[] ids)
    {
        this.lambdaUpdate().set(BondRecord::getDelFlag,PublicCommon.删除).in(BondRecord::getId,ids).update();
        return ids.length;
    }

    /**
     * 删除保证金记录信息
     *
     * @param id 保证金记录主键
     * @return 结果
     */
    @Override
    public int deleteBondRecordById(Long id)
    {
        this.lambdaUpdate().set(BondRecord::getDelFlag,PublicCommon.删除).eq(BondRecord::getId,id).update();
        return 1;
    }

    @Autowired
    private PayUtil payUtil;

    @Autowired
    private StoreService storeService;

    @Autowired
    private BusinessUtil businessUtil;

    @Autowired
    private UserService userService;

    @Override
    public ResponseData bondPay(BondPayReq req, UserVo userVo) {

        userService.storeByEnterprise(userVo);

        //余额支付 验证密码
        if (req.getPayType().equals(PayEnums.balance.getCode())) {
            //判断余额支付
            businessUtil.judgeBalancePay(userVo, req.getAmount(),req.getPayPwd());
        }

        BondRecord bondRecord = new BondRecord();
        bondRecord.setPayType(req.getPayType())
                .setPayOrderNo(generateOrderNo())
                .setAmount(req.getAmount())
                .setUserId(userVo.getUserId());
        this.save(bondRecord);

        //支付
        ResponseData responseData = payUtil.pay(userVo, userVo.getUserId(), req.getPayType(), req.getAmount(), BigDecimal.ZERO, bondRecord.getPayOrderNo(), PaySourceEnums.bond_pay, WalletDetailEnums.BOND_PAY);

        //支付成功/支付金额为0
        if (responseData.getSuccess() || responseData.getCode().equals(210)) {
            //余额支付/苹果支付
            if (req.getPayType().equals(PayEnums.balance.getCode()) || req.getPayType().equals(PayEnums.apple.getCode())) {
                after(bondRecord);
            }
        }

        return responseData;
    }

    @Autowired
    private BondAmountRecordService bondAmountRecordService;

    @Autowired
    private PlatformRecordService platformRecordService;

    /**
     * 支付后操作
     * @param bondRecord
     */
    private void after(BondRecord bondRecord) {
        this.lambdaUpdate().set(BondRecord::getPayStatus,PublicCommon.Pay.已支付)
                .eq(BondRecord::getId, bondRecord.getId()).update();

        storeService.lambdaUpdate().set(Store::getIsBond,2)
                .eq(Store::getId, bondRecord.getUserId()).update();

        //修改用户保证金余额，添加保证金金额记录
        bondAmountRecordService.updateBond(new UserVo(UserEnums.store.getCode(),bondRecord.getUserId()),bondRecord.getId(), PublicCommon.BondWith.缴纳,null, bondRecord.getAmount(),PublicCommon.Wallet.可提现);

        //平台流水
        platformRecordService.addPlatformRecord(new UserVo(UserEnums.store.getCode(),bondRecord.getUserId()),bondRecord.getId(),bondRecord.getAmount(), PlatformRecordEnums.BOND_PAY);
    }


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

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



    @Override
    public ResponseData bondRecordPage(BondRecordPageReq req, UserVo userVo) {
        userService.storeByEnterprise(userVo);
        Page<BondRecord> page = bondRecordMapper.bondRecordPage(new Page<>(req.getPageNo(), req.getPageSize()),req,userVo);
        return ResponseData.success(new PageResult<>(page));
    }

    @Override
    public ResponseData bondAliNotify(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);

        BondRecord cur = baseMapper.selectOne(new QueryWrapper<BondRecord>().lambda().eq(BondRecord::getPayOrderNo, 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.store.getCode(),cur.getUserId()), cur.getId(), cur.getPayType(), cur.getAmount(), cur.getAmount(), cur.getPayOrderNo(), orderNo,BigDecimal.ZERO);
            if (!responseData.getSuccess()) {
                log.error("退款失败：" + cur.getPayOrderNo());
            }
            return responseData;
        }
        if ("TRADE_SUCCESS".equalsIgnoreCase(tradeStatus)) {

            this.lambdaUpdate().set(BondRecord::getAliBusinessId, orderNo).eq(BondRecord::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 bondWxNotify(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");

        BondRecord cur = baseMapper.selectOne(new QueryWrapper<BondRecord>().lambda().eq(BondRecord::getPayOrderNo, 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.store.getCode(),cur.getUserId()), cur.getId(), cur.getPayType(), cur.getAmount(), cur.getAmount(), cur.getPayOrderNo(), cur.getAliBusinessId(),BigDecimal.ZERO);
            if (!responseData.getSuccess()) {
                log.error("退款失败：" + cur.getPayOrderNo());
            }
            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 bondLakalaNotify(Map<String, String> requestMap) {
        System.out.println("requestMap:" + requestMap.toString());
        //流水号
        String payId = requestMap.get("out_order_no");

        BondRecord cur = baseMapper.selectOne(new QueryWrapper<BondRecord>().lambda().eq(BondRecord::getPayOrderNo, payId));
        if (cur == null) {
            log.error("支付信息丢失");
            return ResponseData.error("支付信息丢失");
        }
        if (cur.getPayStatus() == 2) {
            log.error("拉卡拉回调已经开始 回去吧");
            return ResponseData.error("拉卡拉回调已经开始 回去吧");
        }

        //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.getUserId()), cur.getId(), cur.getAmount(), WalletDetailEnums.BOND_RECHARGE);

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

        return ResponseData.error("");
    }

    @Autowired
    private OnlineRecordService onlineRecordService;

    @Override
    public ResponseData bondRecordDetail(Long id, UserVo userVo) {
        userService.storeByEnterprise(userVo);
        BondRecord bondRecord = bondRecordMapper.bondRecordDetail(id,userVo);
        return ResponseData.success(bondRecord);
    }
}
