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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
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.core.domain.AjaxResult;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.enums.CoreExceptionEnum;
import com.ruoyi.common.page.PageResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.WithApplyReq;
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.frequency.appmessage.service.AppMessageService;
import com.ruoyi.frequency.bondamounrecord.service.BondAmountRecordService;
import com.ruoyi.frequency.bondwithdrawalrecord.entity.BondWithdrawalRecord;
import com.ruoyi.frequency.bondwithdrawalrecord.mapper.BondWithdrawalRecordMapper;
import com.ruoyi.frequency.bondwithdrawalrecord.model.result.BondWithdrawalRecordCount;
import com.ruoyi.frequency.bondwithdrawalrecord.service.BondWithdrawalRecordService;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.platformrecord.service.PlatformRecordService;
import com.ruoyi.frequency.store.service.StoreService;
import com.ruoyi.frequency.wallerecord.service.WalletRecordService;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.vo.PageBasic;
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.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 保证金提现记录Service业务层处理
 *
 * @author liwenlong
 * @date 2023-10-31
 */
@Service
public class BondWithdrawalRecordServiceImpl extends ServiceImpl<BondWithdrawalRecordMapper, BondWithdrawalRecord> implements BondWithdrawalRecordService {
    @Autowired
    private BondWithdrawalRecordMapper bondWithdrawalRecordMapper;

    @Autowired
    private UserService userService;

    /**
     * 查询保证金提现记录
     *
     * @param id 保证金提现记录主键
     * @return 保证金提现记录
     */
    @Override
    public BondWithdrawalRecord selectBondWithdrawalRecordById(Long id) {

        BondWithdrawalRecord bondWithdrawalRecord = bondWithdrawalRecordMapper.selectBondWithdrawalRecordById(id);

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

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

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

        return bondWithdrawalRecord;
    }

    /**
     * 查询保证金提现记录列表
     *
     * @param bondWithdrawalRecord 保证金提现记录
     * @return 保证金提现记录
     */
    @Override
    public List<BondWithdrawalRecord> selectBondWithdrawalRecordList(BondWithdrawalRecord bondWithdrawalRecord) {

        List<BondWithdrawalRecord> bondWithdrawalRecords = bondWithdrawalRecordList(bondWithdrawalRecord);

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

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

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

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

    private  List<BondWithdrawalRecord> bondWithdrawalRecordList(BondWithdrawalRecord bondWithdrawalRecord){
        List<BondWithdrawalRecord> bondWithdrawalRecords = bondWithdrawalRecordMapper.selectBondWithdrawalRecordList(bondWithdrawalRecord);
        return bondWithdrawalRecords;
    }

    @Override
    public BondWithdrawalRecordCount statistics(BondWithdrawalRecord bondWithdrawalRecord) {
        List<BondWithdrawalRecord> bondWithdrawalRecords = bondWithdrawalRecordList(bondWithdrawalRecord);
        List<Long> bondWithdrawalRecordIdList = bondWithdrawalRecords.stream().map(x -> x.getId()).collect(Collectors.toList());
        bondWithdrawalRecordIdList.add(-1L);

        return bondWithdrawalRecordMapper.statistics(bondWithdrawalRecordIdList);
    }

    /**
     * 新增保证金提现记录
     *
     * @param bondWithdrawalRecord 保证金提现记录
     * @return 结果
     */
    @Override
    public int insertBondWithdrawalRecord(BondWithdrawalRecord bondWithdrawalRecord) {
        bondWithdrawalRecord.setCreateTime(DateUtils.getNowDate());
        return bondWithdrawalRecordMapper.insert(bondWithdrawalRecord);
    }

    /**
     * 修改保证金提现记录
     *
     * @param bondWithdrawalRecord 保证金提现记录
     * @return 结果
     */
    @Override
    public int updateBondWithdrawalRecord(BondWithdrawalRecord bondWithdrawalRecord) {
        bondWithdrawalRecord.setUpdateTime(DateUtils.getNowDate());
        return bondWithdrawalRecordMapper.updateById(bondWithdrawalRecord);
    }

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

    @Autowired
    private WalletRecordService walletRecordService;

    @Override
    public AjaxResult process(BondWithdrawalRecord bondWithdrawalRecord) {
        this.lambdaUpdate().set(BondWithdrawalRecord::getStatus, bondWithdrawalRecord.getStatus())
                .set(BondWithdrawalRecord::getRefuseReason, bondWithdrawalRecord.getRefuseReason())
                .set(BondWithdrawalRecord::getTransferVoucher, bondWithdrawalRecord.getTransferVoucher())
                .set(BondWithdrawalRecord::getProcessTime, new Date())
                .eq(BondWithdrawalRecord::getId, bondWithdrawalRecord.getId())
                .update();

        BondWithdrawalRecord byId = this.getById(bondWithdrawalRecord.getId());
        //审核失败 提现返还
        if (ObjectUtil.equal(ProcessResultEnums.REJECTED.getCode(), bondWithdrawalRecord.getStatus())) {

            //修改用户保证金余额，添加保证金金额记录
            bondAmountRecordService.updateBond(new UserVo(byId.getUserType(), byId.getUserId()), bondWithdrawalRecord.getId(), PublicCommon.BondWith.提现返还, bondWithdrawalRecord.getId(), byId.getPrice(), PublicCommon.Wallet.可提现);

            //平台流水
            platformRecordService.addPlatformRecord(new UserVo(byId.getUserType(), byId.getUserId()), bondWithdrawalRecord.getId(), byId.getPrice(), PlatformRecordEnums.BOND_WITHDRAWAL_RETURN);

        } else if (ObjectUtil.equal(ProcessResultEnums.APPROVED.getCode(), bondWithdrawalRecord.getStatus())) {
            if (ObjectUtil.isEmpty(byId.getBankCardId())) {
                walletRecordService.updateBalance(new UserVo(byId.getUserType(), byId.getUserId()), WalletDetailEnums.BOND_WITHDRAWAL, byId.getId(), byId.getPrice(), PublicCommon.Wallet.可提现);
            }
        }

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

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


    @Autowired
    private AppMessageService appMessageService;

    @Autowired
    private BusinessUtil businessUtil;

    @Autowired
    private BondAmountRecordService bondAmountRecordService;

    @Autowired
    private StoreService storeService;

    @Autowired
    private PlatformRecordService platformRecordService;

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

        //可提现用户保证金余额
        BigDecimal balance = storeService.getById(userVo.getUserId()).getBondAmount();

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

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

        //修改用户保证金余额，添加保证金金额记录
        bondAmountRecordService.updateBond(userVo, withDrawlRecordId, PublicCommon.BondWith.提现, withDrawlRecordId, req.getAmount().negate(), PublicCommon.Wallet.可提现);

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

        return ResponseData.success();
    }


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

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

        return withdrawalRecord.getId();
    }

    @Override
    public ResponseData withdrawalRecordPage(PageBasic req, UserVo userVo) {
        userService.storeByEnterprise(userVo);
        Page<WithdrawalRecordPageResp> page = baseMapper.withdrawalRecordPage(new Page(req.getPageNo(), req.getPageSize()), userVo);
        return ResponseData.success(new PageResult<>(page));
    }

    @Override
    public ResponseData getDetail(Long id) {

        WithdrawalRecordPageResp detail = baseMapper.getDetail(id);

        return ResponseData.success(detail);
    }
}
