package com.game.business.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

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

import com.game.business.domain.AppUser;
import com.game.business.domain.CfgCommon;
import com.game.business.dto.AppUserTeamTranserDto;
import com.game.business.dto.AppUserTeamTranserRecordDto;
import com.game.business.dto.FinTranDto;
import com.game.business.dto.FinTranRecordDTO;
import com.game.business.service.IAppGameBettingService;
import com.game.business.service.IAppUserService;
import com.game.business.service.ICfgCommonService;
import com.game.business.task.AppUserCountTask;
import com.game.business.util.Md5Utils;
import com.game.business.vo.FinTranVo;
import com.game.common.annotation.DataSource;
import com.game.common.constant.AppSceneType;
import com.game.common.constant.finance.FinTranAddedInfo;
import com.game.common.constant.finance.FinTranType1;
import com.game.common.constant.finance.FinTranType3;
import com.game.common.constant.finance.TranCurrencyType;
import com.game.common.core.domain.HttpRet;
import com.game.common.core.domain.R;
import com.game.common.core.redis.RedisCache;
import com.game.common.enums.DataSourceType;
import com.game.common.utils.DateUtils;
import com.game.common.utils.SecurityUtils;
import com.game.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.game.business.mapper.FinTranRecordMapper;
import com.game.business.domain.FinTranRecord;
import com.game.business.service.IFinTranRecordService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 消费记录Service业务层处理
 *
 * @author game
 * @date 2024-06-18
 */
@Service
public class FinTranRecordServiceImpl extends ServiceImpl<FinTranRecordMapper, FinTranRecord> implements IFinTranRecordService {

    @Autowired
    private FinTranRecordMapper finTranRecordMapper;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private IFinTranRecordService finTranRecordService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ICfgCommonService cfgCommonService;

    @Autowired
    private AppUserCountTask appUserCountTask;

    /**
     * 查询消费记录
     *
     * @param id 消费记录主键
     * @return 消费记录
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public FinTranRecord selectFinTranRecordById(Long id) {
        return finTranRecordMapper.selectFinTranRecordById(id);
    }

    /**
     * 查询消费记录列表
     *
     * @param finTranRecord 消费记录
     * @return 消费记录
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<FinTranRecord> selectFinTranRecordList(FinTranRecord finTranRecord) {
        return finTranRecordMapper.selectFinTranRecordList(finTranRecord);
    }

    /**
     * 新增消费记录
     *
     * @param finTranRecord 消费记录
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int insertFinTranRecord(FinTranRecord finTranRecord) {
                finTranRecord.setCreateTime(DateUtils.getNowDate());
//                finTranRecord.setId(this.nextId());
            return finTranRecordMapper.insertFinTranRecord(finTranRecord);
    }

    /**
     * 修改消费记录
     *
     * @param finTranRecord 消费记录
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int updateFinTranRecord(FinTranRecord finTranRecord) {
        return finTranRecordMapper.updateFinTranRecord(finTranRecord);
    }

    /**
     * 批量删除消费记录
     *
     * @param ids 需要删除的消费记录主键
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int deleteFinTranRecordByIds(Long[] ids) {
        return finTranRecordMapper.deleteFinTranRecordByIds(ids);
    }

    /**
     * 删除消费记录信息
     *
     * @param id 消费记录主键
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int deleteFinTranRecordById(Long id) {
        return finTranRecordMapper.deleteFinTranRecordById(id);
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<FinTranRecord> getUserRecordList(String userId, String beginTime, String endTime) {
        LambdaQueryWrapper<FinTranRecord> queryWrapper = new LambdaQueryWrapper<FinTranRecord>();
        queryWrapper.between(FinTranRecord::getCreateTime,beginTime,endTime);
        if(StringUtils.isNotBlank(userId)){
            queryWrapper.eq(FinTranRecord::getUid,userId);
        }
        return finTranRecordMapper.selectList(queryWrapper);
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public Long nextId() {
        Long id = finTranRecordMapper.nextId();
        return  id < 10000 ? 10000 : id;
    }

    @Override
    @DSTransactional
    @DataSource(DataSourceType.SLAVE)
    public HttpRet<Boolean> transfer(AppUserTeamTranserDto transfer) {
        AppUser toAppUser = appUserService.selectAppUserByUserid(transfer.getToUserId());
        AppUser appUser = appUserService.selectAppUserByUserid(SecurityUtils.getUserId());
        if(null == toAppUser){
            return HttpRet.fail("受益用户不存在");
        }
        if(appUser.getDiamondCoinCash().longValue() < transfer.getMoney().longValue()){
            return HttpRet.fail("可转账金额不足");
        }
        if(StringUtils.isBlank(appUser.getFundPassword())){
            return HttpRet.fail("未设置支付密码");
        }
        if(!Md5Utils.md5(Md5Utils.md5(transfer.getFundPassword()) + appUser.getSalt()).equals(appUser.getFundPassword())){
            return HttpRet.fail("支付密码错误");
        }
        //查询当笔限额
        CfgCommon cfgSignleCommon = cfgCommonService.getCfg(1);
        if(null != cfgSignleCommon && transfer.getMoney() > Double.parseDouble(cfgSignleCommon.getCfgValue())){
            return HttpRet.fail("转账失败超出单笔最大限额");
        }
        //查询当日限额
        CfgCommon cfgCommon = cfgCommonService.getCfg(0);
        if(null != cfgCommon){
            double limit = Double.parseDouble(cfgCommon.getCfgValue());
            //查询当前总转账金额
            LambdaQueryWrapper<FinTranRecord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(FinTranRecord::getFromUid,SecurityUtils.getUserId());
            queryWrapper.eq(FinTranRecord::getTranType1,FinTranType1.U_Outcome_Coin.getType());
            queryWrapper.eq(FinTranRecord::getTranType3,FinTranType3.TRANSFER_TO_TEAM_DiamondCoin.getType());
            List<FinTranRecord> finTranRecords = finTranRecordService.selecListByWrapper(queryWrapper);
            if(null != finTranRecords && finTranRecords.size()>0){
                double curMoney = finTranRecords.stream().mapToDouble(FinTranRecord::getDiamondCoinChange).sum();
                if(curMoney >= limit){
                    return HttpRet.fail("转账失败，超出当日转账限额".concat(String.valueOf(limit)));
                }
            }
        }
        //当前用户扣减余额
        AppUser updateAppUser = new AppUser();
        updateAppUser.setUserid(appUser.getUserid());
        updateAppUser.setDiamondCoin(appUser.getDiamondCoin() - transfer.getMoney());
        updateAppUser.setDiamondCoinCash(appUser.getDiamondCoinCash() - transfer.getMoney());
        updateAppUser.setDiamondCoinTotal(appUser.getDiamondCoinTotal() - transfer.getMoney());
        //扣减余额
        appUserService.updateAppUser(updateAppUser);

        FinTranAddedInfo addedInfo = FinTranAddedInfo.createTranInfo(appUser.getUserid(), 0, 0, AppSceneType.Scene_None, "");
        FinTranRecord tran = FinTranRecord.initFinTranRecordSomeParams(addedInfo, FinTranType3.TRANSFER_TO_TEAM_DiamondCoin, FinTranType1.U_Outcome_Balance, appUser);
        tran.setDiamondCoinChange(transfer.getMoney() * -1);
        tran.setAfterDiamondCoin(appUser.getDiamondCoin() + transfer.getMoney());
        tran.setCurrencyType(TranCurrencyType.Balance.getType());
        tran.setRemarks("团队转账");
        finTranRecordService.insertFinTranRecord(tran);

        //受益用户增加余额
        AppUser toUpdateAppUser = new AppUser();
        toUpdateAppUser.setUserid(toAppUser.getUserid());
        toUpdateAppUser.setDiamondCoin(toAppUser.getDiamondCoin() + transfer.getMoney());
        toUpdateAppUser.setDiamondCoinCash(toAppUser.getDiamondCoinCash() + transfer.getMoney());
        updateAppUser.setDiamondCoinTotal(toAppUser.getDiamondCoinTotal() + transfer.getMoney());
        //增加余额
        appUserService.updateAppUser(toUpdateAppUser);

        FinTranAddedInfo toAddedInfo = FinTranAddedInfo.createTranInfo(appUser.getUserid(), 0, 0, AppSceneType.Scene_None, "");
        FinTranRecord toTran = FinTranRecord.initFinTranRecordSomeParams(toAddedInfo, FinTranType3.TRANSFER_TO_TEAM_DiamondCoin, FinTranType1.U_Income_Coin_Balance, toAppUser);
        toTran.setDiamondCoinChange(transfer.getMoney());
        toTran.setAfterDiamondCoin(appUser.getDiamondCoin() + transfer.getMoney());
        toTran.setCurrencyType(TranCurrencyType.Balance.getType());
        toTran.setFromUid(appUser.getUserid());
        tran.setRemarks("团队转账");
        finTranRecordService.insertFinTranRecord(toTran);
        //清除用户缓存
        redisCache.deleteObject("U:UserInfo:".concat(String.valueOf(appUser.getUserid())));
        redisCache.deleteObject("U:UserInfo:".concat(String.valueOf(toAppUser.getUserid())));
        //更新用户可提现余额
        appUserCountTask.updateWithdrawAble(appUser.getUserid());
        return HttpRet.success("转账成功",true);
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<FinTranRecord> transferRecord(AppUserTeamTranserRecordDto transerRecordDto) {
        Long userId = SecurityUtils.getUserId();
        LambdaQueryWrapper<FinTranRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(FinTranRecord::getCreateTime,transerRecordDto.getBeginTime().concat(" 00:00:00"),transerRecordDto.getEndTime().concat(" 23:59:59"));
        queryWrapper.eq(FinTranRecord::getTranType3,FinTranType3.TRANSFER_TO_TEAM_DiamondCoin.getType());
        queryWrapper.eq(FinTranRecord::getTranType1,FinTranType1.U_Income_Coin_Balance.getType());
        if(transerRecordDto.getType() == 0){
            //转出
            queryWrapper.eq(FinTranRecord::getFromUid,userId);
            if(null != transerRecordDto.getUserId() && transerRecordDto.getUserId().longValue() > 0){
                queryWrapper.eq(FinTranRecord::getToUid,transerRecordDto.getUserId());
            }
        }else if(transerRecordDto.getType() == 1){
            //转入
            queryWrapper.eq(FinTranRecord::getToUid,userId);
            if(null != transerRecordDto.getUserId()  && transerRecordDto.getUserId().longValue() > 0){
                queryWrapper.eq(FinTranRecord::getFromUid,transerRecordDto.getUserId());
            }
        }
        List<FinTranRecord> list = finTranRecordMapper.selectList(queryWrapper);
        return list;
    }

    @DataSource(DataSourceType.SLAVE)
    @Override
    public List<FinTranRecord> selecListByWrapper(LambdaQueryWrapper<FinTranRecord> queryWrapper){
        List<FinTranRecord> list = finTranRecordMapper.selectList(queryWrapper);
        return list;
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public JSONObject selecFinTranRecordCount(FinTranRecordDTO finTranRecordDTO) {

        JSONObject jsonObject = new JSONObject();

        // 用户总统计（充值）
        Map<String, BigDecimal> rechargeCount = finTranRecordMapper.getRechargeSum(finTranRecordDTO.getUserId());
        jsonObject.put("rechargeCount", rechargeCount);

        // 用户总统计（兑换）
        Map<String, BigDecimal> exchangeCount = finTranRecordMapper.getExchangeSum(finTranRecordDTO.getUserId());
        jsonObject.put("exchangeCount", exchangeCount);

        // 用户总统计（提现）
        BigDecimal withdraw = finTranRecordMapper.getWithdrawSum(finTranRecordDTO.getUserId());
        jsonObject.put("withdraw", withdraw);

        // 根据时间查询充值分类统计
        List<Map<String, Object>> rechargeByDateSum =  finTranRecordMapper.getRechargeByDateSum(finTranRecordDTO);
        if(rechargeByDateSum == null){
            rechargeByDateSum = new ArrayList<>();
        }
        jsonObject.put("rechargeByDateSum", rechargeByDateSum);


        // 根据时间查询提现分类统计
        List<Map<String, Object>> withdrawByDateSum =  finTranRecordMapper.getWithdrawByDateSum(finTranRecordDTO);
        if(withdrawByDateSum == null){
            withdrawByDateSum = new ArrayList<>();
        }
        jsonObject.put("withdrawByDateSum", withdrawByDateSum);

        return jsonObject;
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<FinTranVo> selectTranList(FinTranDto finTranDto) {
        if(null == finTranDto.getUserId()){
            finTranDto.setUserId(SecurityUtils.getUserId());
        }
        String weekBegin = null;
        String weekend = null;
        Date curDate = DateUtil.date();
        if(1 == finTranDto.getType().intValue()){
            curDate = DateUtil.offsetDay(curDate,-15); //上一周期
        }
        int curDay = Integer.parseInt(DateUtil.format(curDate,"dd"));
        if(curDay <= 15){
            weekBegin = DateUtil.format(DateUtil.beginOfMonth(curDate),"yyyy-MM-dd").concat(" 00:00:00");
            weekend = DateUtil.format(curDate,"yyyy-MM-".concat("15").concat(" 23:59:59"));
        }else{
            weekBegin = DateUtil.format(curDate,"yyyy-MM-".concat("15").concat(" 00:00:00"));
            weekend = DateUtil.format(DateUtil.endOfMonth(curDate),"yyyy-MM-dd").concat(" 23:59:59");
        }
        finTranDto.setBeginTime(weekBegin);
        finTranDto.setEndTime(weekend);
        if(0 == finTranDto.getTranType().intValue()){
            //直播收益
            finTranDto.setTranType1(FinTranType1.U_Income_Coin.getType());
            finTranDto.setTranType3(FinTranType3.CONSUM_LIVE_ROOM_REWARD.getType());
        }else{
            finTranDto.setTranType3(FinTranType3.CHARGE_IN_INVITE.getType());
        }
        return finTranRecordMapper.selectTranList(finTranDto);
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<FinTranRecord> selectUserTran(Integer type1, String type3s, Long userId, Date beginDate, Date endDate,Integer withDrawFlag) {
        LambdaQueryWrapper<FinTranRecord> queryWrapper = new LambdaQueryWrapper<>();
        if(null != userId){
            queryWrapper.eq(FinTranRecord::getUid,userId);
        }
        if(null != withDrawFlag) {
            queryWrapper.eq(FinTranRecord::getWithdrawFlag, withDrawFlag);//满足提现的充值
        }
        if(null != beginDate){
            queryWrapper.ge(FinTranRecord::getCreateTime,beginDate);
        }
        if(null != endDate){
            queryWrapper.lt(FinTranRecord::getCreateTime,endDate);
        }
        if(null != type1){
            queryWrapper.eq(FinTranRecord::getTranType1,type1);
        }
        if(StringUtils.isNotBlank(type3s)){
            String[] typeArr = type3s.split(",");
            queryWrapper.in(FinTranRecord::getTranType3, Arrays.asList(typeArr));
        }
        queryWrapper.orderByAsc(FinTranRecord::getCreateTime);
        queryWrapper.eq(FinTranRecord::getCurrencyType,4);//余额流水
        return finTranRecordMapper.selectList(queryWrapper);
    }
}