package com.game.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.math.BigDecimal;
import java.rmi.ServerException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.game.business.domain.FinTranRecord;
import com.game.business.service.IFinTranRecordService;
import com.game.business.vo.ApiUserInfoVo;
import com.game.common.annotation.DataSource;
import com.game.common.constant.finance.FinTranType3;
import com.game.common.core.redis.RedisCache;
import com.game.common.enums.DataSourceType;
import com.game.common.utils.DateUtils;
import com.game.common.utils.MoneyUtils;
import com.game.common.utils.StringUtils;
import lombok.extern.log4j.Log4j2;
import lombok.val;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.game.business.mapper.AppUserMapper;
import com.game.business.domain.AppUser;
import com.game.business.service.IAppUserService;

/**
 * app用户Service业务层处理
 *
 * @author game
 * @date 2024-06-18
 */
@Service
@Log4j2
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements IAppUserService {
    @Autowired
    private AppUserMapper appUserMapper;

    @Autowired
    private RedissonClient redisson;

    @Autowired
    private IFinTranRecordService finTranRecordService;

    @Autowired
    private RedisCache redisCache;

    /**
     * 查询app用户
     *
     * @param userid app用户主键
     * @return app用户
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public AppUser selectAppUserByUserid(Long userid) {
        return appUserMapper.selectAppUserByUserid(userid);
    }

    /**
     * 查询app用户列表
     *
     * @param appUser app用户
     * @return app用户
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<AppUser> selectAppUserList(AppUser appUser) {
        appUser.setDelFlag(0L);//查询未删除用户
        return appUserMapper.selectAppUserList(appUser);
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<AppUser> selectTeamUserList() {
        return appUserMapper.selectTeamUserList();
    }

    /**
     * 新增app用户
     *
     * @param appUser app用户
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int insertAppUser(AppUser appUser) {
                appUser.setCreateTime(DateUtils.getNowDate());
//                appUser.setUserid(this.nextId());
            return appUserMapper.insertAppUser(appUser);
    }

    /**
     * 修改app用户
     *
     * @param appUser app用户
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int updateAppUser(AppUser appUser) {
        return appUserMapper.updateAppUser(appUser);
    }

    /**
     * 批量删除app用户
     *
     * @param userids 需要删除的app用户主键
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int deleteAppUserByUserids(Long[] userids) {
        return appUserMapper.deleteAppUserByUserids(userids);
    }

    /**
     * 删除app用户信息
     *
     * @param userid app用户主键
     * @return 结果
     */
    @Override
    @DataSource(DataSourceType.SLAVE)
    public int deleteAppUserByUserid(Long userid) {
        return appUserMapper.deleteAppUserByUserid(userid);
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public int getCount(Long pid, String beginTime, String endTime) {
        LambdaQueryWrapper<AppUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AppUser::getPid, pid);
        queryWrapper.eq(AppUser::getDelFlag,0);
        if(StringUtils.isNotBlank(beginTime)){
            queryWrapper.ge(AppUser::getInviteBindTime,beginTime);
        }
        if(StringUtils.isNotBlank(endTime)){
            queryWrapper.le(AppUser::getInviteBindTime,endTime);
        }
        return appUserMapper.selectCount(queryWrapper).intValue();
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public boolean getMobileCount(String userName) {
        LambdaQueryWrapper<AppUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AppUser::getMobile, userName);
        return appUserMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<AppUser> selectListByIds(List<Long> ids) {
        LambdaQueryWrapper<AppUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(AppUser::getUserid,ids);
        queryWrapper.eq(AppUser::getDelFlag,0);
        return appUserMapper.selectList(queryWrapper);
    }

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

    @Override
    @DataSource(DataSourceType.SLAVE)
    public int updateUserAmount(FinTranRecord finTranRecord) throws Exception{
        int res = 0;
        int finRes = 0;
        RLock rLock = redisson.getLock("app_user_amount_".concat(String.valueOf(finTranRecord.getUid())));
        boolean tryLock = false;
        try {
            tryLock = rLock.tryLock(10L,10L, TimeUnit.SECONDS); //等待10秒 最多持有锁10秒
            if(tryLock){
                AppUser appUser = appUserMapper.selectAppUserByUserid(finTranRecord.getUid());
                if(null != appUser){
                    AppUser updateAppUser = new AppUser();
                    updateAppUser.setUserid(appUser.getUserid());
                    if(2 == finTranRecord.getCurrencyType().intValue()){
                        //金币
                        updateAppUser.setCoin(finTranRecord.getCoinChange());
                        updateAppUser.setCoinCash(MoneyUtils.consumeCash(appUser.getCoin(),appUser.getCoinCash(),finTranRecord.getCoinChange()));
                    }else if(4 == finTranRecord.getCurrencyType().intValue()){
                        //余额
                        updateAppUser.setDiamondCoin(finTranRecord.getDiamondCoinChange());
                        updateAppUser.setDiamondCoinTotal(finTranRecord.getDiamondCoinChange());
                        updateAppUser.setDiamondCoinCash(MoneyUtils.consumeCash(appUser.getDiamondCoin(),appUser.getDiamondCoinCash(),finTranRecord.getDiamondCoinChange()));
                    }
                    if(finTranRecord.getTranType3().intValue() == FinTranType3.CASH_DIAMOND_INCOME_BACK.getType()){
                        //回退已提现金额
                        updateAppUser.setWithdraw(finTranRecord.getDiamondCoinChange() * -1);
                    }
                    res = appUserMapper.updateUserMoney(updateAppUser);
                    if(res > 0) {
                        //清除用户缓存
                        redisCache.deleteObject("U:UserInfo:".concat(String.valueOf(appUser.getUserid())));
                        AppUser afterUser = appUserMapper.selectAppUserByUserid(finTranRecord.getUid());
                        if (2 == finTranRecord.getCurrencyType().intValue()) {
                            finTranRecord.setAfterCoin(afterUser.getCoin());
                        } else if (4 == finTranRecord.getCurrencyType().intValue()) {
                            finTranRecord.setAfterDiamondCoin(afterUser.getDiamondCoin());
                        }
                        finRes = finTranRecordService.insertFinTranRecord(finTranRecord);
                    }
                }
            }else{
                log.info("用户{}钱包更新失败：{}",finTranRecord.getUid(),tryLock);
            }
        } catch (InterruptedException e) {
            log.info("用户{}钱包更新失败：{}",finTranRecord.getUid(),e);
        } finally {
            if(finRes < 1){
                String params = "";
                if(null != finTranRecord){
                    params = JSONObject.toJSONString(finTranRecord);
                }
                log.info("res:{},finRes:{},更新失败：{}",res,finRes,params);
                throw new Exception("更新失败");
            }
            rLock.unlock();
        }
        return res;
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public Map<String, BigDecimal> getUserCount(Long userId) {
        return appUserMapper.getUserCount(userId);
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public ApiUserInfoVo getUserInfo(Long userId) {
        return appUserMapper.getUserInfo(userId);
    }
}