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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.DictConstant;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.enums.CoreExceptionEnum;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.WithApplyReq;
import com.ruoyi.controller.req.WithdrawalRecordPageReq;
import com.ruoyi.controller.resp.WithdrawalRecordPageResp;
import com.ruoyi.enums.PlatformRecordEnums;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.message.AppMessageEnums;
import com.ruoyi.enums.process.ProcessResultEnums;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.appmessage.service.AppMessageService;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.illegaldeductionrecord.service.IllegalDeductionRecordService;
import com.ruoyi.frequency.klkwithdrawalrecord.entity.KlkWithdrawalRecord;
import com.ruoyi.frequency.klkwithdrawalrecord.service.KlkWithdrawalRecordService;
import com.ruoyi.frequency.platformrecord.service.PlatformRecordService;
import com.ruoyi.frequency.sale.entity.Sale;
import com.ruoyi.frequency.sale.service.SaleService;
import com.ruoyi.frequency.store.entity.Store;
import com.ruoyi.frequency.store.service.StoreService;
import com.ruoyi.frequency.userwithdrawalway.service.UserWithdrawalWayService;
import com.ruoyi.frequency.userwithdrawalwaywi.service.UserWithdrawalWayWiService;
import com.ruoyi.frequency.wallerecord.mapper.WalletRecordMapper;
import com.ruoyi.frequency.wallerecord.service.WalletRecordService;
import com.ruoyi.frequency.withdrawalconfig.service.WithdrawalConfigService;
import com.ruoyi.frequency.withdrawalrecord.entity.WithdrawalRecord;
import com.ruoyi.frequency.withdrawalrecord.mapper.WithdrawalRecordMapper;
import com.ruoyi.frequency.withdrawalrecord.model.result.WithdrawalRecordCount;
import com.ruoyi.frequency.withdrawalrecord.service.WithdrawalRecordService;
import com.ruoyi.klk.service.KlkService;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.vo.UserInfo;
import com.ruoyi.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 提现记录Service业务层处理
 *
 * @author liwenlong
 * @date 2023-07-20
 */
@Service
public class WithdrawalRecordServiceImpl extends ServiceImpl<WithdrawalRecordMapper, WithdrawalRecord> implements WithdrawalRecordService {
    @Autowired
    private WithdrawalRecordMapper withdrawalRecordMapper;

    /**
     * 查询提现记录
     *
     * @param id 提现记录主键
     * @return 提现记录
     */
    @Override
    public WithdrawalRecord selectWithdrawalRecordById(Long id) {

        WithdrawalRecord withdrawalRecord = withdrawalRecordMapper.selectWithdrawalRecordById(id);

        if (withdrawalRecord != null) {
            withdrawalRecord.setName(withdrawalRecord.getFullName());
            Set<UserVo> userVoSet = CollectionUtil.newHashSet(new UserVo(withdrawalRecord.getUserType(), withdrawalRecord.getUserId()));

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

            withdrawalRecord.setUserInfo(userMap.get(new UserVo(withdrawalRecord.getUserType(), withdrawalRecord.getUserId())));
        }
        return withdrawalRecord;
    }

    @Autowired
    private UserService userService;

    /**
     * 查询提现记录列表
     *
     * @param withdrawalRecord 提现记录
     * @return 提现记录
     */
    @Override
    public List<WithdrawalRecord> selectWithdrawalRecordList(WithdrawalRecord withdrawalRecord) {

        List<WithdrawalRecord> withdrawalRecords = withdrawalRecordList(withdrawalRecord);

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

            Set<UserVo> userVoSet = withdrawalRecords.stream().map(s -> new UserVo(s.getUserType(), s.getUserId())).collect(Collectors.toSet());

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

            withdrawalRecords.stream().forEach(s -> {
                s.setUserInfo(userMap.get(new UserVo(s.getUserType(), s.getUserId())));
            });
        }

        return withdrawalRecords;
    }

    private List<WithdrawalRecord> withdrawalRecordList(WithdrawalRecord withdrawalRecord) {
        List<WithdrawalRecord> withdrawalRecords = withdrawalRecordMapper.selectWithdrawalRecordList(withdrawalRecord);
        return withdrawalRecords;
    }

    @Override
    public WithdrawalRecordCount statistics(WithdrawalRecord withdrawalRecord) {
        List<WithdrawalRecord> withdrawalRecords = withdrawalRecordList(withdrawalRecord);
        List<Long> withdrawalRecordIdList = withdrawalRecords.stream().map(x -> x.getId()).collect(Collectors.toList());
        withdrawalRecordIdList.add(-1L);
        return withdrawalRecordMapper.statistics(withdrawalRecordIdList);
    }

    /**
     * 新增提现记录
     *
     * @param withdrawalRecord 提现记录
     * @return 结果
     */
    @Override
    public int insertWithdrawalRecord(WithdrawalRecord withdrawalRecord) {
        withdrawalRecord.setCreateTime(DateUtils.getNowDate());
        return withdrawalRecordMapper.insertWithdrawalRecord(withdrawalRecord);
    }

    /**
     * 修改提现记录
     *
     * @param withdrawalRecord 提现记录
     * @return 结果
     */
    @Override
    public int updateWithdrawalRecord(WithdrawalRecord withdrawalRecord) {
        withdrawalRecord.setUpdateTime(DateUtils.getNowDate());
        return withdrawalRecordMapper.updateWithdrawalRecord(withdrawalRecord);
    }

    /**
     * 批量删除提现记录
     *
     * @param ids 需要删除的提现记录主键
     * @return 结果
     */
    @Override
    public int deleteWithdrawalRecordByIds(Long[] ids) {
        return withdrawalRecordMapper.deleteWithdrawalRecordByIds(ids);
    }

    /**
     * 删除提现记录信息
     *
     * @param id 提现记录主键
     * @return 结果
     */
    @Override
    public int deleteWithdrawalRecordById(Long id) {
        return withdrawalRecordMapper.deleteWithdrawalRecordById(id);
    }


    @Autowired
    private KlkService klkService;

    @Autowired
    private KlkWithdrawalRecordService klkWithdrawalRecordService;

    @Override
    public AjaxResult process(WithdrawalRecord withdrawalRecord) {

        this.lambdaUpdate().set(WithdrawalRecord::getStatus, withdrawalRecord.getStatus())
                .set(WithdrawalRecord::getRefuseReason, withdrawalRecord.getRefuseReason())
                .set(WithdrawalRecord::getTransferVoucher, withdrawalRecord.getTransferVoucher())
                .set(WithdrawalRecord::getProcessTime, new Date())
                .eq(WithdrawalRecord::getId, withdrawalRecord.getId())
                .update();

        WithdrawalRecord byId = this.getById(withdrawalRecord.getId());

        //审核失败 提现返还
        if (ObjectUtil.equal(ProcessResultEnums.REJECTED.getCode(), withdrawalRecord.getStatus())) {

            //修改用户余额，添加余额记录
            walletRecordService.updateBalance(new UserVo(byId.getUserType(), byId.getUserId()), WalletDetailEnums.WITH_FAIL_RETURN, withdrawalRecord.getId(), byId.getPrice().add(byId.getServiceCharge()).add(byId.getViolationDeduction()), PublicCommon.Wallet.可提现);

            //平台流水
            platformRecordService.addPlatformRecord(new UserVo(byId.getUserType(), byId.getUserId()), byId.getId(), byId.getPrice().add(byId.getServiceCharge()).add(byId.getViolationDeduction()), PlatformRecordEnums.WITH_FAIL_RETURN);

            if (ObjectUtil.equal(UserEnums.store.getCode(), byId.getUserType())) {
                //返还扣款金额
                illegalDeductionRecordService.updateViolationDeduction(byId.getUserId(), byId.getId(), byId.getViolationDeduction(), 4, null, null, null);

                //平台流水
                platformRecordService.addPlatformRecord(new UserVo(byId.getUserType(), byId.getUserId()), byId.getId(), byId.getViolationDeduction(), PlatformRecordEnums.VIOLATION_DEDUCTION_RETURN);
            }
        }

        //提现结果提醒
        if (ObjectUtil.equal(ProcessResultEnums.APPROVED.getCode(), withdrawalRecord.getStatus())) {
            //审核失败 提现返还
            appMessageService.addAppMessage(new UserVo(byId.getUserType(), byId.getUserId()), byId.getId(), AppMessageEnums.WITHDRAWAL_SUCCESS);

        } else {
            //审核失败 提现返还
            appMessageService.addAppMessage(new UserVo(byId.getUserType(), byId.getUserId()), byId.getId(), AppMessageEnums.WITHDRAWAL_FAIL);
        }

        WithdrawalRecord withdrawalRecordDB = getById(withdrawalRecord.getId());

        if (withdrawalRecordDB.getPrice() == null || withdrawalRecordDB.getPrice().compareTo(BigDecimal.ZERO) == 0) {
            // 将提现记录状态修改为4转账中
            withdrawalRecordMapper.update(null, new LambdaUpdateWrapper<WithdrawalRecord>()
                    .eq(WithdrawalRecord::getDelFlag, PublicCommon.启用)
                    .eq(WithdrawalRecord::getId, byId.getId())
                    .set(WithdrawalRecord::getStatus, 5));
        } else {
            // 审核成功走下述逻辑
            if (withdrawalRecord.getStatus() == 2) {
                // 审核成功，走后续的提现步骤
                klkService.withdrawal(byId);

                // 将提现记录状态修改为4转账中
                withdrawalRecordMapper.update(null, new LambdaUpdateWrapper<WithdrawalRecord>()
                        .eq(WithdrawalRecord::getDelFlag, PublicCommon.启用)
                        .eq(WithdrawalRecord::getId, byId.getId())
                        .set(WithdrawalRecord::getStatus, 4));
            }

        }

        return AjaxResult.success();
    }

    @Autowired
    private AppMessageService appMessageService;

    @Autowired
    private BusinessUtil businessUtil;

    @Autowired
    private WithdrawalConfigService withdrawalConfigService;

    @Autowired
    private WalletRecordService walletRecordService;


    @Autowired
    private WalletRecordMapper walletRecordMapper;

    @Autowired
    private StoreService storeService;

    @Autowired
    private IllegalDeductionRecordService illegalDeductionRecordService;


    @Autowired
    private PlatformRecordService platformRecordService;

    @Autowired
    private SaleService saleService;


    @Override
    public ResponseData apply(WithApplyReq req, UserVo userVo) {

        //判断支付密码
        if (!businessUtil.payPwdTrue(userVo, req.getPayPwd())) {
            return ResponseData.error(CoreExceptionEnum.PWD_ERROR);
        }

        //提现判断
        withdrawalConfigService.withdrawalJudge(userVo, req.getAmount());

        BigDecimal balance = BigDecimal.ZERO;

        switch (UserEnums.getUserEnums(userVo.getUserType())) {
            case store:
                //可提现用户余额
                Date beginOfMonth = DateUtil.beginOfMonth(new Date());
                balance = walletRecordMapper.selectMonthBeforeAmount(beginOfMonth, userVo);
                break;
            case sale:
                Sale sale = saleService.getById(userVo.getUserId());
                balance = sale.getBalance();
                break;
            default:
                break;
        }

        req.setUserType(userVo.getUserType());
        //计算手续费
        BigDecimal serviceCharge = getServiceCharge(req, balance);

        //扣款
        BigDecimal violationDeduction = BigDecimal.ZERO;

        if (ObjectUtil.equal(UserEnums.store.getCode(), userVo.getUserType())) {

            Store store = storeService.getById(userVo.getUserId());

            //扣除手续费 金额
            BigDecimal price = req.getAmount().subtract(serviceCharge);

            violationDeduction = store.getViolationDeduction().compareTo(price) == 1
                    ? price : store.getViolationDeduction();
        }


        //提现记录
        Long withDrawlRecordId = createWithDrawlRecord(userVo, req, serviceCharge, violationDeduction);

        //修改用户余额，添加余额记录
        walletRecordService.updateBalance(userVo, WalletDetailEnums.WITH_DEDU, withDrawlRecordId, req.getAmount().negate(), PublicCommon.Wallet.可提现);

        //平台流水
        platformRecordService.addPlatformRecord(userVo, withDrawlRecordId, req.getAmount().negate(), PlatformRecordEnums.WITH_DEDU);

        if (ObjectUtil.equal(UserEnums.store.getCode(), userVo.getUserType())) {

            //扣除扣款金额
            illegalDeductionRecordService.updateViolationDeduction(userVo.getUserId(), withDrawlRecordId, violationDeduction.negate(), 3, null, null, null);

            //平台流水
            platformRecordService.addPlatformRecord(userVo, withDrawlRecordId, violationDeduction, PlatformRecordEnums.VIOLATION_DEDUCTION);

        }

        return ResponseData.success(withDrawlRecordId);
    }

    public static void main(String[] args) {
        System.out.println(new Date(1717171200000L));
    }

    @Override
    public ResponseData withdrawalRecordPage(WithdrawalRecordPageReq req, UserVo userVo) {

        LambdaUpdateWrapper<WithdrawalRecord> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(WithdrawalRecord::getUserId, userVo.getUserId());
        lambdaUpdateWrapper.eq(WithdrawalRecord::getUserType, userVo.getUserType());
        if (req.getBeginTime() != null) {
            lambdaUpdateWrapper.ge(BaseEntity::getCreateTime, req.getBeginTime());
        }
        if (req.getEndTime() != null) {
            lambdaUpdateWrapper.le(BaseEntity::getCreateTime, req.getEndTime());
        }
        lambdaUpdateWrapper.eq(WithdrawalRecord::getDelFlag, PublicCommon.启用);
        lambdaUpdateWrapper.orderByDesc(BaseEntity::getCreateTime);

        List<WithdrawalRecord> withdrawalRecordList = this.baseMapper.selectList(lambdaUpdateWrapper);
        //按月筛选
        Map<String, List<WithdrawalRecord>> withdrawaMap = new LinkedHashMap<>();

        Map<Long, KlkWithdrawalRecord> klkWithdrawalRecordMap = new HashMap<>();

        List<Long> withdrawalIdList = withdrawalRecordList.stream().map(x -> x.getId()).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(withdrawalIdList)) {
            List<KlkWithdrawalRecord> klkWithdrawalRecordList = klkWithdrawalRecordService.list(new QueryWrapper<KlkWithdrawalRecord>().lambda().
                    in(KlkWithdrawalRecord::getWithdrawalRecordId, withdrawalIdList));

            klkWithdrawalRecordList.stream().forEach(x -> {
                klkWithdrawalRecordMap.put(x.getWithdrawalRecordId(), x);
            });

        }

        if (CollectionUtil.isNotEmpty(withdrawalRecordList)) {
            for (WithdrawalRecord cur : withdrawalRecordList) {
                cur.setAmount(cur.getPrice());
                cur.setKlkWithdrawalRecord(klkWithdrawalRecordMap.get(cur.getId()));
                String yearMonth = DateUtil.year(cur.getCreateTime()) + "年" + (DateUtil.month(cur.getCreateTime()) + 1) + "月";
                if (!withdrawaMap.containsKey(yearMonth)) {
                    withdrawaMap.put(yearMonth, new ArrayList<>());
                }
                withdrawaMap.get(yearMonth).add(cur);
            }

        }
        List<Map> resultList = new ArrayList<>();
        Iterator<Map.Entry<String, List<WithdrawalRecord>>> iterator = withdrawaMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<WithdrawalRecord>> next = iterator.next();
            Map map = new HashMap();
            map.put("date", next.getKey());
            map.put("list", next.getValue());
            resultList.add(map);
        }

        return ResponseData.success(resultList);
    }

    @Override
    public ResponseData getDetail(Long id) {

        WithdrawalRecordPageResp detail = baseMapper.getDetail(id);
        KlkWithdrawalRecord klkWithdrawalRecord = klkWithdrawalRecordService.getOne(new QueryWrapper<KlkWithdrawalRecord>().lambda().eq(KlkWithdrawalRecord::getWithdrawalRecordId, id));
        detail.setKlkWithdrawalRecord(klkWithdrawalRecord);

        if (klkWithdrawalRecord != null) {
            detail.setTransferFinishTime(klkWithdrawalRecord.getTransferFinishTime());
        }
        return ResponseData.success(detail);
    }


    private BigDecimal getServiceCharge(WithApplyReq req, BigDecimal totalPrice) {
        //提现手续费(比例)
        BigDecimal commission;

        SysDictData one = null;

        switch (UserEnums.getUserEnums(req.getUserType())) {
            case store:
                //提现手续费字典
                one = businessUtil.getDict(DictConstant.提现手续费);
                break;
            case sale:
                one = businessUtil.getDict(DictConstant.推广员提现手续费);
                break;
            default:
                break;
        }

        if (one == null) {
            throw new CustomException(CoreExceptionEnum.NO_DICTIONARIES);
        }
        try {
            commission = new BigDecimal(one.getDictValue());
        } catch (Exception e) {
            throw new CustomException(CoreExceptionEnum.DICTIONARIES_ERROR);
        }

        // 手续费
        BigDecimal subBalance = req.getAmount().multiply(commission);

        //判断余额
        if (totalPrice.compareTo(req.getAmount()) == -1) {
            throw new CustomException(CoreExceptionEnum.BALANCE_INSUFFICIENT);
        }
        return subBalance;
    }

    @Autowired
    private UserWithdrawalWayService userWithdrawalWayService;

    @Autowired
    private UserWithdrawalWayWiService userWithdrawalWayWiService;

    /**
     * 提现记录
     *
     * @param userVo
     * @param req
     * @param serviceCharge
     * @return
     */
    private Long createWithDrawlRecord(UserVo userVo, WithApplyReq req, BigDecimal serviceCharge, BigDecimal violationDeduction) {

//        //查询用户提现账号
//        UserWithdrawalWay userWithdrawalWay = userWithdrawalWayService.getById(req.getUserWWayId());
//
//        //记录这次提现的提现账号
//        UserWithdrawalWayWi withdrawalWayWi =  userWithdrawalWayWiService.addUserWithdrawalWayWi(userWithdrawalWay);

        //提现记录
        WithdrawalRecord withdrawalRecord = new WithdrawalRecord()
                .setUserId(userVo.getUserId())
                .setUserType(userVo.getUserType())
                .setPrice(req.getAmount().subtract(violationDeduction).subtract(serviceCharge))
                .setServiceCharge(serviceCharge)
                .setTotalAmount(req.getAmount())
                .setDelFlag(PublicCommon.启用)
                .setRemarks(req.getRemark())
                .setViolationDeduction(violationDeduction)
                .setStatus(ProcessResultEnums.PENDING.getCode())
                .setBank(req.getBank())
                .setSubbranch(req.getSubbranch())
                .setBankCard(req.getBankCard())
                .setFullName(req.getFullName())
                .setBankCardId(req.getBankCardId());
        this.save(withdrawalRecord);

        return withdrawalRecord.getId();
    }

}
