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

import cn.hutool.core.bean.BeanUtil;
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.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.UpscaleAuthReq;
import com.ruoyi.enums.PlatformRecordEnums;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.process.ProcessResultEnums;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.auth.entity.Auth;
import com.ruoyi.frequency.auth.mapper.AuthMapper;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.highendauth.entity.HighendAuth;
import com.ruoyi.frequency.highendauth.mapper.HighendAuthMapper;
import com.ruoyi.frequency.highendauth.model.result.HighendAuthCount;
import com.ruoyi.frequency.highendauth.service.HighendAuthService;
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.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.*;
import java.util.stream.Collectors;

/**
 * 高端认证Service业务层处理
 *
 * @author liwenlong
 * @date 2023-10-20
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class HighendAuthServiceImpl extends ServiceImpl<HighendAuthMapper, HighendAuth> implements HighendAuthService {
    @Autowired
    private HighendAuthMapper highendAuthMapper;

    @Autowired
    private UserService userService;

    /**
     * 查询高端认证
     *
     * @param id 高端认证主键
     * @return 高端认证
     */
    @Override
    public HighendAuth selectHighendAuthById(Long id) {
        HighendAuth auth = highendAuthMapper.selectHighendAuthById(id);

        if (auth != null) {
            Set<UserVo> userVoSet = new HashSet<>();

            userVoSet.add(new UserVo(UserEnums.store.getCode(), auth.getStoreId()));

            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, null);

            auth.setUserInfo(userMap.get(new UserVo(UserEnums.store.getCode(), auth.getStoreId())));
        }
        return auth;
    }

    /**
     * 查询高端认证列表
     *
     * @param highendAuth 高端认证
     * @return 高端认证
     */
    @Override
    public List<HighendAuth> selectHighendAuthList(HighendAuth highendAuth) {

        List<HighendAuth> highendAuths = highendAuth(highendAuth);

        if (highendAuths != null && highendAuths.size() > 0) {

            Set<UserVo> userVoSet = highendAuths.stream().map(s -> new UserVo(UserEnums.store.getCode(), s.getStoreId())).collect(Collectors.toSet());
            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, null);

            highendAuths.stream().forEach(s -> {
                s.setUserInfo(userMap.get(new UserVo(UserEnums.store.getCode(), s.getStoreId())));
            });
        }

        return highendAuths;
    }

    private List<HighendAuth> highendAuth(HighendAuth highendAuth) {
        List<HighendAuth> highendAuths = highendAuthMapper.selectHighendAuthList(highendAuth);
        return highendAuths;
    }

    @Override
    public HighendAuthCount statistics(HighendAuth highendAuth) {
        List<HighendAuth> highendAuths = highendAuth(highendAuth);
        List<Long> highendAuthIdList = highendAuths.stream().map(x -> x.getId()).collect(Collectors.toList());
        highendAuthIdList.add(-1L);

        return highendAuthMapper.statistics(highendAuthIdList);
    }

    @Autowired
    private AuthMapper authMapper;

    /**
     * 新增高端认证
     *
     * @param highendAuth 高端认证
     * @return 结果
     */
    @Override
    public int insertHighendAuth(HighendAuth highendAuth) {

        Auth auth = authMapper.selectOne(new QueryWrapper<Auth>().lambda()
                .eq(Auth::getType, 3)
                .eq(Auth::getStoreId, highendAuth.getStoreId())
                .eq(Auth::getDelFlag, PublicCommon.启用)
        );

        //判断是否进行酷家乐认证
        if (auth != null && ObjectUtil.isNotEmpty(auth.getResult())) {
            if (auth.getResult().equals(ProcessResultEnums.PENDING.getCode())) {
                throw new CustomException("您正在进行酷家乐认证，请勿重复申请");
            } else if (auth.getResult().equals(ProcessResultEnums.APPROVED.getCode())) {
                throw new CustomException("您已进行酷家乐认证，请勿重复认证");
            }
        }

        int count = this.count(new QueryWrapper<HighendAuth>().lambda()
                .eq(HighendAuth::getDelFlag, PublicCommon.启用)
                .eq(HighendAuth::getStoreId, highendAuth.getStoreId()));
        //判断表现师是否重复创建
        if (count > 0) {
            throw new CustomException("表现师已存在");
        }

        highendAuth.setCreateTime(DateUtils.getNowDate());

        //查询普通认证信息
        Auth authCommon = authMapper.selectOne(new QueryWrapper<Auth>().lambda()
                .eq(Auth::getType, 1)
                .eq(Auth::getStoreId, highendAuth.getStoreId())
                .eq(Auth::getDelFlag, PublicCommon.启用).last(" limit 1")
        );
        if (authCommon != null) {
            highendAuth.setName(authCommon.getName());
            highendAuth.setIdcardNo(authCommon.getIdcardNo());
            highendAuth.setSpecialityArea(authCommon.getSpecialityArea());
            highendAuth.setIdFront(authCommon.getIdFront());
            highendAuth.setIdBack(authCommon.getIdBack());
            highendAuth.setIdHandHand(authCommon.getIdHandHand());
            highendAuth.setBranchWork(authCommon.getBranchWork());
        }

        return highendAuthMapper.insert(highendAuth);
    }

    /**
     * 修改高端认证
     *
     * @param highendAuth 高端认证
     * @return 结果
     */
    @Override
    public int updateHighendAuth(HighendAuth highendAuth) {
        highendAuth.setUpdateTime(DateUtils.getNowDate());
        highendAuth.setStatus(2);
        return highendAuthMapper.updateById(highendAuth);
    }

    /**
     * 批量删除高端认证
     *
     * @param ids 需要删除的高端认证主键
     * @return 结果
     */
    @Override
    public int deleteHighendAuthByIds(Long[] ids) {
        this.lambdaUpdate().set(HighendAuth::getDelFlag, PublicCommon.删除).in(HighendAuth::getId, ids).update();
        return ids.length;
    }

    /**
     * 删除高端认证信息
     *
     * @param id 高端认证主键
     * @return 结果
     */
    @Override
    public int deleteHighendAuthById(Long id) {
        this.lambdaUpdate().set(HighendAuth::getDelFlag, PublicCommon.删除).eq(HighendAuth::getId, id).update();
        return 1;
    }

    @Autowired
    private StoreService storeService;

    @Override
    public int uploadCode(HighendAuth highendAuth) {
        HighendAuth h = this.getById(highendAuth.getId());

        this.lambdaUpdate().set(HighendAuth::getStatus, 4).eq(HighendAuth::getId, h.getId()).update();

        storeService.lambdaUpdate().set(Store::getWecomQrcode, highendAuth.getWecomQrcode()).eq(Store::getId, h.getStoreId()).update();

        return 1;
    }

    @Autowired
    private BusinessUtil businessUtil;

    @Autowired
    private PayUtil payUtil;

    @Override
    public ResponseData highendAuth(UpscaleAuthReq req, UserVo userVo) {

        userService.storeByEnterprise(userVo);

        //判断认证状态
        HighendAuth auth = judgeAuthStatus(userVo);

        //判断已支付/未支付 认证金额
        Boolean isPay = auth == null || auth.getIsPay() == 1;

        BeanUtil.copyProperties(req, auth);
        auth.setStoreId(userVo.getUserId())
                .setIsPay(isPay ? 1 : 2);//是否缴纳 1没有 2 缴纳
        return payAuth(auth, req, userVo);
    }

    private ResponseData noPayAuth(HighendAuth auth) {
        this.updateById(auth);
        return ResponseData.success();
    }

    private ResponseData payAuth(HighendAuth auth, UpscaleAuthReq req, UserVo userVo) {
        //需要支付
        //查询字典配置--普通认证缴纳金额
        SysDictData dict = businessUtil.getDict(DictConstant.高端认证缴纳金额);
        BigDecimal amount = dict == null ? BigDecimal.ZERO : new BigDecimal(dict.getDictValue());

        //支付金额
        auth.setAmount(amount);

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

        //支付订单号
        auth.setPayOrderNo(generateOrderNo());

        this.updateById(auth);

        //支付
        ResponseData responseData = payUtil.pay(userVo, auth.getId(), req.getPayType(), amount, BigDecimal.ZERO, auth.getPayOrderNo(), PaySourceEnums.highend_auth_pay, WalletDetailEnums.HEIGHT_AUTH_PAY);

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

        return responseData;
    }

    /**
     * 判断认证状态
     *
     * @param userVo
     * @return
     */
    private HighendAuth judgeAuthStatus(UserVo userVo) {

        //判断认证状态
        HighendAuth auth = this.getOne(new QueryWrapper<HighendAuth>().lambda()
                .eq(HighendAuth::getStoreId, userVo.getUserId())
                .eq(HighendAuth::getDelFlag, PublicCommon.启用)
        );
        if (auth == null || auth.getStatus() == 1) {
            throw new CustomException("请联系平台 完善您的线下认证");
        }
        if (auth.getStatus() == 3) {
            throw new CustomException("您已认证成功，请勿重复认证");
        }
        return auth;
    }

    @Autowired
    private PlatformRecordService platformRecordService;

    /**
     * 支付后操作
     *
     * @param auth
     */
    private void after(HighendAuth auth) {

        this.lambdaUpdate().set(HighendAuth::getPayStatus, PublicCommon.Pay.已支付)
                .set(HighendAuth::getIsPay, 2)
                .set(HighendAuth::getStatus, 3)
                .eq(HighendAuth::getId, auth.getId()).update();

        //平台流水
        platformRecordService.addPlatformRecord(new UserVo(UserEnums.store.getCode(), auth.getStoreId()), auth.getId(), auth.getAmount(), PlatformRecordEnums.HEIGHT_AUTH_PAY);
    }

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

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

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

        HighendAuth cur = baseMapper.selectOne(new QueryWrapper<HighendAuth>().lambda().eq(HighendAuth::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.getStoreId()), 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(HighendAuth::getAliBusinessId, orderNo).eq(HighendAuth::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 highendAuthWxNotify(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");

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

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

            //添加支付记录
            onlineRecordService.addOnlineRecord(new UserVo(UserEnums.customer.getCode(), cur.getStoreId()), cur.getId(), cur.getAmount(), WalletDetailEnums.HEIGHT_AUTH_PAY);

            businessUtil.setOutTradeNo(payId);

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

        return ResponseData.error("");
    }

    @Autowired
    private OnlineRecordService onlineRecordService;
}
