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

import cn.hutool.core.bean.BeanUtil;
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.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.core.domain.BaseEntity;
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.WalletPageReq;
import com.ruoyi.controller.resp.WalletPageResp;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.customer.mapper.CustomerMapper;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.illegaldeductionrecord.model.result.OrderInfoResp;
import com.ruoyi.frequency.klkwithdrawalrecord.entity.KlkWithdrawalRecord;
import com.ruoyi.frequency.klkwithdrawalrecord.service.KlkWithdrawalRecordService;
import com.ruoyi.frequency.onlinerecord.entity.OnlineRecord;
import com.ruoyi.frequency.onlinerecord.mapper.OnlineRecordMapper;
import com.ruoyi.frequency.sale.mapper.SaleMapper;
import com.ruoyi.frequency.store.mapper.StoreMapper;
import com.ruoyi.frequency.wallerecord.entity.WalletRecord;
import com.ruoyi.frequency.wallerecord.mapper.WalletRecordMapper;
import com.ruoyi.frequency.wallerecord.model.param.EditUserBalanceParam;
import com.ruoyi.frequency.wallerecord.model.result.WalletRecordCount;
import com.ruoyi.frequency.wallerecord.service.WalletRecordService;
import com.ruoyi.frequency.withdrawalrecord.entity.WithdrawalRecord;
import com.ruoyi.frequency.withdrawalrecord.service.WithdrawalRecordService;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.vo.BodyIdReq;
import com.ruoyi.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 钱包记录Service业务层处理
 *
 * @author liwenlong
 * @date 2023-07-20
 */
@Service
public class WalletRecordServiceImpl extends ServiceImpl<WalletRecordMapper, WalletRecord> implements WalletRecordService {
    @Autowired
    private WalletRecordMapper walletRecordMapper;

    /**
     * 查询钱包记录
     *
     * @param id 钱包记录主键
     * @return 钱包记录
     */
    @Override
    public WalletRecord selectWalletRecordById(Long id) {
        return walletRecordMapper.selectWalletRecordById(id);
    }

    /**
     * 查询钱包记录列表
     *
     * @param walletRecord 钱包记录
     * @return 钱包记录
     */
    @Override
    public List<WalletRecord> selectWalletRecordList(WalletRecord walletRecord) {

        List<WalletRecord> walletRecords = walletRecordList(walletRecord);

        if (walletRecords.size() > 0) {
            walletRecords.stream().forEach(s -> {
                s.setRecord(WalletDetailEnums.getName(s.getRecordType()));
            });
        }

        return walletRecords;
    }


    private List<WalletRecord> walletRecordList(WalletRecord walletRecord) {
        List<WalletRecord> walletRecords = baseMapper.selectWalletRecordList(walletRecord);
        return walletRecords;
    }

    /**
     * 新增钱包记录
     *
     * @param walletRecord 钱包记录
     * @return 结果
     */
    @Override
    public int insertWalletRecord(WalletRecord walletRecord) {
        walletRecord.setCreateTime(DateUtils.getNowDate());
        return walletRecordMapper.insertWalletRecord(walletRecord);
    }

    /**
     * 修改钱包记录
     *
     * @param walletRecord 钱包记录
     * @return 结果
     */
    @Override
    public int updateWalletRecord(WalletRecord walletRecord) {
        walletRecord.setUpdateTime(DateUtils.getNowDate());
        return walletRecordMapper.updateWalletRecord(walletRecord);
    }

    /**
     * 批量删除钱包记录
     *
     * @param ids 需要删除的钱包记录主键
     * @return 结果
     */
    @Override
    public int deleteWalletRecordByIds(Long[] ids) {
        return walletRecordMapper.deleteWalletRecordByIds(ids);
    }

    /**
     * 删除钱包记录信息
     *
     * @param id 钱包记录主键
     * @return 结果
     */
    @Override
    public int deleteWalletRecordById(Long id) {
        return walletRecordMapper.deleteWalletRecordById(id);
    }


    @Autowired
    private BusinessUtil businessUtil;

    @Override
    public ResponseData editUserBalance(EditUserBalanceParam param) {

        //查询用户余额
        BigDecimal userBalance = businessUtil.getUserBalance(new UserVo(param.getUserType(), param.getUserId()));

        if (ObjectUtil.isNotEmpty(param.getBalance()) && param.getBalance().compareTo(userBalance) != 0) {
            if (param.getBalance().compareTo(userBalance) == 1) {

                //充值金额
                BigDecimal addPrice = param.getBalance().subtract(userBalance);

                this.updateBalance(new UserVo(param.getUserType(), param.getUserId()), WalletDetailEnums.PLAT_ADD, param.getUserId(), addPrice, PublicCommon.Wallet.可提现);

            } else {
                //扣除金额
                BigDecimal subPrice = param.getBalance().subtract(userBalance);

                this.updateBalance(new UserVo(param.getUserType(), param.getUserId()), WalletDetailEnums.PLAT_SUB, param.getUserId(), subPrice, PublicCommon.Wallet.可提现);
            }
        }

        return ResponseData.success();
    }


    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private StoreMapper storeMapper;

    @Autowired
    private SaleMapper saleMapper;

    @Override
    public void updateBalance(UserVo userVo, WalletDetailEnums walletDetailEnums, Long objectId, BigDecimal updatePrice, Integer status) {
        if (updatePrice.compareTo(BigDecimal.ZERO) == 0 || ObjectUtil.equal(PublicCommon.Wallet.到账取消, status)) {
            return;
        }

        switch (userVo.getUserType()) {
            case 1:
                if (updatePrice.compareTo(BigDecimal.ZERO) == 1) {
                    customerMapper.addBalance(userVo.getUserId(), updatePrice);
                } else {
                    boolean subBalance = customerMapper.subBalance(userVo.getUserId(), updatePrice.negate());
                    if (!subBalance) {
                        throw new CustomException(CoreExceptionEnum.BALANCE_INSUFFICIENT);
                    }
                }
                break;
            case 2:
                if (updatePrice.compareTo(BigDecimal.ZERO) == 1) {
                    storeMapper.addBalance(userVo.getUserId(), updatePrice);
                } else {
                    boolean subBalance = storeMapper.subBalance(userVo.getUserId(), updatePrice.negate());
                    if (!subBalance) {
                        throw new CustomException(CoreExceptionEnum.BALANCE_INSUFFICIENT);
                    }
                }
                break;
            case 3:
                if (updatePrice.compareTo(BigDecimal.ZERO) == 1) {
                    saleMapper.addBalance(userVo.getUserId(), updatePrice);
                    //累计收益
                    saleMapper.addIncome(userVo.getUserId(), updatePrice);
                } else {
                    boolean subBalance = saleMapper.subBalance(userVo.getUserId(), updatePrice.negate());
                    if (!subBalance) {
                        throw new CustomException(CoreExceptionEnum.BALANCE_INSUFFICIENT);
                    }
                }
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + userVo.getUserType());
        }

        //添加钱包记录
        addWalletRecord(userVo, objectId, updatePrice, walletDetailEnums, null, status);
    }

    @Override
    public void updateBalance(UserVo userVo, WalletDetailEnums walletDetailEnums, String remark, Long objectId, BigDecimal updatePrice, Integer status) {
        if (updatePrice.compareTo(BigDecimal.ZERO) == 0 || ObjectUtil.equal(PublicCommon.Wallet.到账取消, status)) {
            throw new CustomException(CoreExceptionEnum.ERROR_PARAM);
        }

        switch (userVo.getUserType()) {
            case 1:
                if (updatePrice.compareTo(BigDecimal.ZERO) == 1) {
                    customerMapper.addBalance(userVo.getUserId(), updatePrice);
                } else {
                    boolean subBalance = customerMapper.subBalance(userVo.getUserId(), updatePrice.negate());
                    if (!subBalance) {
                        throw new CustomException(CoreExceptionEnum.BALANCE_INSUFFICIENT);
                    }
                }
                break;
            case 2:
                if (updatePrice.compareTo(BigDecimal.ZERO) == 1) {
                    storeMapper.addBalance(userVo.getUserId(), updatePrice);
                } else {
                    boolean subBalance = storeMapper.subBalance(userVo.getUserId(), updatePrice.negate());
                    if (!subBalance) {
                        throw new CustomException(CoreExceptionEnum.BALANCE_INSUFFICIENT);
                    }
                }
                break;
            case 3:
                if (updatePrice.compareTo(BigDecimal.ZERO) == 1) {
                    saleMapper.addBalance(userVo.getUserId(), updatePrice);
                    //累计收益
                    saleMapper.addIncome(userVo.getUserId(), updatePrice);
                } else {
                    boolean subBalance = saleMapper.subBalance(userVo.getUserId(), updatePrice.negate());
                    if (!subBalance) {
                        throw new CustomException(CoreExceptionEnum.BALANCE_INSUFFICIENT);
                    }
                }
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + userVo.getUserType());
        }

        //添加钱包记录
        addWalletRecord(userVo, objectId, updatePrice, walletDetailEnums, remark, status);
    }

    /**
     * 增加余额记录
     *
     * @param userVo            用户
     * @param walletDetailEnums 类型名称
     * @param orderId           订单id
     * @param price             金额
     */
    public void addWalletRecord(UserVo userVo, Long orderId, BigDecimal price, WalletDetailEnums walletDetailEnums, String remark, Integer status) {
        if (price.setScale(2, BigDecimal.ROUND_HALF_UP).compareTo(new BigDecimal(0)) != 0) {
            WalletRecord walletRecord = new WalletRecord();
            walletRecord.setUserId(userVo.getUserId());
            walletRecord.setUserType(userVo.getUserType());
            walletRecord.setObjectId(orderId);
            walletRecord.setStatus(status);
            walletRecord.setRecordType(walletDetailEnums.getCode());
            walletRecord.setPrice(price);

            if (ObjectUtil.equal(PublicCommon.Wallet.可提现, status)) {
                walletRecord.setCanWithTime(new Date());
            } else if (ObjectUtil.equal(PublicCommon.Wallet.不可提现, status)) {
                walletRecord.setNoWithTime(new Date());
            }

            //获取用户当前余额
            BigDecimal userBalance = businessUtil.getUserBalance(userVo);

            walletRecord.setCurrentBalance(userBalance);
            walletRecord.setRemark(remark);

            this.save(walletRecord);
        }
    }


    @Autowired
    private UserService userService;

    @Override
    public ResponseData walletPage(WalletPageReq req, UserVo userVo) {

        userService.storeByEnterprise(userVo);

        Page<WalletPageResp> page = null;
        if (ObjectUtil.equal(UserEnums.store.getCode(), userVo.getUserType()) && ObjectUtil.isEmpty(req.getType())) {
            page = this.baseMapper.walletStorePage(new Page<>(req.getPageNo(), req.getPageSize()), req, userVo);
        } else if (ObjectUtil.equal(UserEnums.sale.getCode(), userVo.getUserType()) && ObjectUtil.isEmpty(req.getType())) {
            page = this.baseMapper.walletSalePage(new Page<>(req.getPageNo(), req.getPageSize()), req, userVo);
        } else {
            page = this.baseMapper.walletPage(new Page<>(req.getPageNo(), req.getPageSize()), req, userVo);
        }

        if (page.getRecords().size() > 0) {
            page.getRecords().stream().forEach(s -> {
                if (ObjectUtil.isNotEmpty(s.getRecordType())) {
                    s.setRecord(WalletDetailEnums.getName(s.getRecordType()));
                }
            });
        }

        // 查询分页结果
        return ResponseData.success(new PageResult<>(page));
    }

    private List<Integer> getExpenditureList() {
        List<Integer> recordTypeList = new ArrayList<>();
        recordTypeList.add(WalletDetailEnums.WITH_DEDU.getCode());
        recordTypeList.add(WalletDetailEnums.ORDER_PAY.getCode());
        recordTypeList.add(WalletDetailEnums.PLAT_SUB.getCode());
        recordTypeList.add(WalletDetailEnums.PLATFORM_AUTH_PAY.getCode());
        recordTypeList.add(WalletDetailEnums.HEIGHT_AUTH_PAY.getCode());
        recordTypeList.add(WalletDetailEnums.BOND_PAY.getCode());
        recordTypeList.add(WalletDetailEnums.ADJUST_PRICE_PAY.getCode());
        recordTypeList.add(WalletDetailEnums.MALL_ORDER_PAY.getCode());
        recordTypeList.add(WalletDetailEnums.GIVE_BALANCE.getCode());
        return recordTypeList;
    }

    @Autowired
    private OnlineRecordMapper onlineRecordMapper;

    @Override
    public ResponseData expenditurePage(WalletPageReq req, UserVo userVo) {
        LambdaUpdateWrapper<WalletRecord> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(WalletRecord::getUserId, userVo.getUserId());
        lambdaUpdateWrapper.eq(WalletRecord::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(WalletRecord::getDelFlag, PublicCommon.启用);

        lambdaUpdateWrapper.in(WalletRecord::getRecordType, getExpenditureList());
        lambdaUpdateWrapper.orderByDesc(BaseEntity::getCreateTime);

        List<WalletRecord> walletRecordList = this.baseMapper.selectList(lambdaUpdateWrapper);
        if (CollectionUtil.isNotEmpty(walletRecordList)) {
            for (WalletRecord cur : walletRecordList) {
                cur.setIsOnline(2);
            }

        }
        //加入在线支付记录

        List<OnlineRecord> onlineRecords = onlineRecordMapper.selectList(new QueryWrapper<OnlineRecord>().lambda().eq(OnlineRecord::getUserId, userVo.getUserId())
                .eq(OnlineRecord::getUserType, userVo.getUserType()));
        for (OnlineRecord onlineRecord : onlineRecords) {
            WalletRecord walletRecord = new WalletRecord();
            BeanUtil.copyProperties(onlineRecord, walletRecord);
            walletRecord.setIsOnline(1);
            walletRecord.setRecordType(onlineRecord.getObjectType());

            walletRecordList.add(walletRecord);
        }


        //按月筛选
        Map<String, List<WalletRecord>> walletMap = new LinkedHashMap<>();

        if (CollectionUtil.isNotEmpty(walletRecordList)) {
            for (WalletRecord cur : walletRecordList) {
                cur.setRecord(WalletDetailEnums.getName(cur.getRecordType()));
                String yearMonth = DateUtil.year(cur.getCreateTime()) + "年" + (DateUtil.month(cur.getCreateTime()) + 1) + "月";
                if (!walletMap.containsKey(yearMonth)) {
                    walletMap.put(yearMonth, new ArrayList<>());
                }
                walletMap.get(yearMonth).add(cur);
            }

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

        return ResponseData.success(resultList);
    }

    @Autowired
    private WithdrawalRecordService withdrawalRecordService;
    @Autowired
    private KlkWithdrawalRecordService klkWithdrawalRecordService;

    @Override
    public ResponseData walletDetail(BodyIdReq req, UserVo userVo) {
        WalletRecord walletRecord = baseMapper.walletDetail(req.getId());
        walletRecord.setRecord(WalletDetailEnums.getName(walletRecord.getRecordType()));
        if (walletRecord.getRecordType().equals(WalletDetailEnums.WITH_DEDU.getCode())
                || walletRecord.getRecordType().equals(WalletDetailEnums.WITH_FAIL_RETURN.getCode())) {

            WithdrawalRecord withdrawalRecord = withdrawalRecordService.getById(walletRecord.getObjectId());
            if (withdrawalRecord != null) {
                KlkWithdrawalRecord klkWithdrawalRecord = klkWithdrawalRecordService.getOne(new QueryWrapper<KlkWithdrawalRecord>().lambda().eq(KlkWithdrawalRecord::getWithdrawalRecordId, withdrawalRecord.getId()));
                if (klkWithdrawalRecord != null) {
                    walletRecord.setTransferCompletionTime(klkWithdrawalRecord.getTransferFinishTime());
                }
            }
        } else if (walletRecord.getRecordType().equals(WalletDetailEnums.ORDER_PAY.getCode())
                || walletRecord.getRecordType().equals(WalletDetailEnums.ORDER_INCOME.getCode())
                || walletRecord.getRecordType().equals(WalletDetailEnums.ORDER_RETURN.getCode())
                || walletRecord.getRecordType().equals(WalletDetailEnums.ADJUST_PRICE_PAY.getCode())
                || walletRecord.getRecordType().equals(WalletDetailEnums.DEPOSIT_REFUND.getCode())
                || walletRecord.getRecordType().equals(WalletDetailEnums.GIVE_ORDER_PAY.getCode())
                || walletRecord.getRecordType().equals(WalletDetailEnums.GIVE_ORDER_RETURN.getCode())
        ) {
            OrderInfoResp orderInfo = businessUtil.getOrderInfo(walletRecord.getObjectId());
            if (orderInfo != null) {
                walletRecord.setOrderTime(orderInfo.getCreateTime());
                walletRecord.setOrderNo(orderInfo.getOrderNo());
            }
        }
        return ResponseData.success(walletRecord);
    }

    @Override
    public WalletRecordCount statistics(WalletRecord walletRecord) {
        List<WalletRecord> walletRecordList = walletRecordList(walletRecord);

        WalletRecordCount count = new WalletRecordCount();

        walletRecordList.stream().forEach(x -> {
            if (x.getPrice().compareTo(BigDecimal.ZERO) == 1) {
                count.setIncome(count.getIncome().add(x.getPrice()));
            } else if (x.getPrice().compareTo(BigDecimal.ZERO) == -1) {
                count.setExpenditure(count.getExpenditure().add(x.getPrice()));
            }
        });

        return count;
    }


}
