package com.game.business.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.game.business.domain.*;
import com.game.business.dto.AppItemCountDTO;
import com.game.business.service.*;
import com.game.business.util.Common;
import com.game.business.util.im.TencentCloudImUtil;
import com.game.business.vo.AppGameItemBettingVO;
import com.game.common.constant.finance.FinTranType1;
import com.game.common.constant.finance.FinTranType2;
import com.game.common.constant.finance.FinTranType3;
import com.game.common.core.domain.HttpRet;
import com.game.common.core.redis.RedisCache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

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

@Component
public class AppGameBettingTask {

    @Autowired
    private IAppGameBettingService appGameBettingService;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private IFinTranRecordService finTranRecordService;

    @Autowired
    private IAppGameLotteryService appGameLotteryService;

    @Autowired
    private IAppGameService appGameService;

    @Autowired
    private IAppGameClassifyService appGameClassifyService;

    @Autowired
    private IAppGameItemService appGameItemService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IAppUserCountService appUserCountService;

    @Autowired
    private AppUserCountTask appUserCountTask;

    public void gameDataTask(String message, String gameCodeFinal) throws Exception {

        JSONArray dataArry = JSONArray.parseArray(message);

        Integer type = null;

        for (int i = 0; i < dataArry.size(); i++) {
            JSONObject jsonObject = dataArry.getJSONObject(i);
            if(jsonObject.containsKey("type")){
                type = jsonObject.getInteger("type");
                break;
            }
        }

        if(type == null){
//            System.out.println("游戏socket推送类型为空。");
            return;
        }

        // 更新倒计时
        if(type == 1){

//            JSONArray gameDataArry = null;
            String gameCode = null;
            String time = null;
            String classCode = null;
            Integer state = null;
            for (int i = 0; i < dataArry.size(); i++) {
                JSONObject jsonObject = dataArry.getJSONObject(i);
                if(jsonObject.containsKey("data")){
                    gameCode = jsonObject.getString("id");
                }
                if(jsonObject.containsKey("time")){
                    time = jsonObject.getString("time");
                }
                if(jsonObject.containsKey("id")){
                    classCode = jsonObject.getString("id");
                }
                if(jsonObject.containsKey("state")){
                    state = jsonObject.getInteger("state");
                }
            }

            if(classCode == null){
//                System.out.println("游戏socket推送倒计时，平台ID为空。");
                return;
            }

            if(gameCode == null){
//                System.out.println("游戏socket推送倒计时，data对象为空。");
                return;
            }

            if(time == null || time.trim().isEmpty()){
//                System.out.println("游戏socket推送倒计时，time为空。");
                return;
            }

            if(gameCode.equals(Common.GAME_FOUR_CODE)){
                if(state == null || state != 0){
                    return;
                }
            }

            if(gameCode.equals(Common.GAME_FIVE_CODE)){
                if(state == null || state != 1){
                    return;
                }
            }

            AppGameClassify appGameClassify = appGameClassifyService.getByCode(classCode);
            if(appGameClassify == null){
//                System.out.println("开奖游戏平台不存在：" + classCode);
                return;
            }

            List<AppGame> appGameList = appGameService.selectAppGameByClassId(appGameClassify.getId());
            if(appGameList == null || appGameList.isEmpty()){
//                System.out.println("开奖游戏平台没有游戏：" + classCode);
                return;
            }
            Map<String, List<AppGame>> codeGameMap = appGameList.stream().collect(Collectors.groupingBy(AppGame::getCode));

            if(!gameCodeFinal.equals(gameCode)){
                return;
            }
            if(!codeGameMap.containsKey(gameCode)){
//                    System.out.println("开奖游戏不存在：" + gameCode);
                return;
            }

            AppGame appGame = codeGameMap.get(gameCode).get(0);
            appGame.setGameTime(time);
            appGameService.updateAppGame(appGame);
            return;
        }

        if(type != 2 && type != 3){
            return;
        }

        JSONArray gameArry = null;
        String classCode = null;
        for (int i = 0; i < dataArry.size(); i++) {
            JSONObject jsonObject = dataArry.getJSONObject(i);
            if(jsonObject.containsKey("gameTypeSortArrayVOS")){
                gameArry = jsonObject.getJSONArray("gameTypeSortArrayVOS");
            }
            if(jsonObject.containsKey("id")){
                classCode = jsonObject.getString("id");
            }
        }

        if(gameArry == null){
//            System.out.println("游戏socket推送期号或开奖，gameTypeSortArrayVOS对象为空。");
            return;
        }

        if(classCode == null){
//            System.out.println("游戏socket推送期号或开奖，平台ID为空。");
            return;
        }

        AppGameClassify appGameClassify = appGameClassifyService.getByCode(classCode);
        if(appGameClassify == null){
//            System.out.println("开奖游戏平台不存在：" + classCode);
            return;
        }

        List<AppGame> appGameList = appGameService.selectAppGameByClassId(appGameClassify.getId());
        if(appGameList == null || appGameList.isEmpty()){
//            System.out.println("开奖游戏平台没有游戏：" + classCode);
            return;
        }
        Map<String, List<AppGame>> codeGameMap = appGameList.stream().collect(Collectors.groupingBy(AppGame::getCode));

        for (int i = 0; i < gameArry.size(); i++) {
            JSONObject gameLotteryObject = gameArry.getJSONObject(i);
            String gameCode = gameLotteryObject.getString("id");

            if(gameCode == null){
//                System.out.println("游戏socket推送期号或开奖，游戏ID为空。");
                continue;
            }
            if(!gameCodeFinal.equals(gameCode)){
                continue;
            }

            if(!codeGameMap.containsKey(gameCode)){
//                System.out.println("开奖游戏不存在：" + gameCode);
                continue;
            }
            AppGame appGame = codeGameMap.get(gameCode).get(0);

            String gameDate = gameLotteryObject.getString("gameDate");
            if(gameDate == null){
//                System.out.println("游戏socket推送期号或开奖，期号为空。");
                continue;
            }

            if(type == 3){
                appGame.setGameDate(gameDate);
                appGameService.updateAppGame(appGame);

                // 修改倍数
                if(gameCode.equals(Common.GAME_ONE_CODE)){

                    String gameLotteryBet = gameLotteryObject.getString("gameLotteryBet");
                    if(StringUtils.isBlank(gameLotteryBet)){
                        continue;
                    }

                    gameLotteryBet = gameLotteryBet.replace(" ", "").trim();
                    JSONArray items = JSONArray.parseArray(gameLotteryBet);
                    if(items == null || items.isEmpty()){
                       continue;
                    }

                    AppGameItem appGameItem = new AppGameItem();
                    appGameItem.setGameId(appGame.getId());
                    List<AppGameItem> itemList = appGameItemService.selectAppGameItemList(appGameItem);

                    if(itemList == null || itemList.isEmpty()){
                        continue;
                    }

                    if(itemList.size() != items.size()){
                        continue;
                    }

                    // 升序排序
                    Collections.sort(itemList, Comparator.comparing(AppGameItem::getItemLocation));

                    for (int j = 0; j < itemList.size(); j++) {
                        AppGameItem gameItem = itemList.get(j);
                        gameItem.setItemMultiple(items.getDouble(j));
                        appGameItemService.updateAppGameItem(gameItem);
                    }
                }

                continue;
            }

            Integer isLottery = gameLotteryObject.getInteger("isLottery");
            String gameLotterySucc = gameLotteryObject.getString("gameLotterySucc");

            if(isLottery != 1){
                continue;
            }

            if(gameLotterySucc == null || gameLotterySucc.trim().isEmpty()){
//                System.out.println("游戏socket推送倒计时，time为空。");
                continue;
            }

            long count = appGameLotteryService.selectCount(appGame.getClassifyId(), appGame.getId(), gameDate);

            if(count > 0){
//                System.out.println("游戏socket推送开奖，当前期已开过将，游戏编码：" + gameCode + "，期号：" + gameDate);
                continue;
            }

            // 保存开奖记录
            AppGameLottery appGameLottery = new AppGameLottery();
            appGameLottery.setGameId(appGame.getId());
            appGameLottery.setClassId(appGame.getClassifyId());
            appGameLottery.setGameDate(gameDate);
            appGameLottery.setIsLottery(isLottery);
            appGameLottery.setGameRecordDate(new Date());
            appGameLottery.setGameLotterySucc(gameLotterySucc);
            appGameLotteryService.save(appGameLottery);

            lotteryTask(appGame, appGameClassify, gameLotterySucc, gameDate);
        }

    }

    @Async("asyncExecutor")
    public void lotteryTask(AppGame appGame, AppGameClassify appGameClassify, String gameLotterySucc, String gameDate) throws Exception {

        this.updateItme(appGame.getId(), gameLotterySucc);

        List<String> userIds = this.gameBettingTask(appGameClassify.getId(), appGame.getId(), gameDate, gameLotterySucc);

        appUserCountService.staticsUserCount(appGame.getId(),null,appGame.getGameDate());

        // 给中奖人发送刷新余额通知
        sendMsg(userIds);

        //更新可提现余额
        for(String userId : userIds) {
            appUserCountTask.updateWithdrawAble(Long.parseLong(userId));
        }
    }

    public void updateItme(Long gameId, String gameLotterySucc){

        // 获取上次开奖结果
        List<AppItemCountDTO> itemCountList = new ArrayList<>();
        String gameLotterySuccCache =  redisCache.getCacheObject("G:GameCount:" + gameId);
        if(gameLotterySuccCache != null && !gameLotterySuccCache.trim().isEmpty()){
            itemCountList = JSONArray.parseArray(gameLotterySuccCache, AppItemCountDTO.class);
        }

        // 修改游戏选项
        String [] bettingItems = gameLotterySucc.split(",");
        List<AppItemCountDTO> nowItemCountList = new ArrayList<>();
        for(int j = 0; j < bettingItems.length; j++) {
            String bettingItemStr = bettingItems[j];

            AppItemCountDTO appItemCountDTO = new AppItemCountDTO();
            appItemCountDTO.setGameId(gameId);
            appItemCountDTO.setItemLocation(bettingItemStr);
            appItemCountDTO.setConsecutive(1);

            AppGameItem appGameItem = new AppGameItem();
            appGameItem.setGameId(gameId);
            appGameItem.setItemLocation(bettingItemStr);
            // 开奖次数
            appGameItemService.updateLotteryCount(appGameItem);

            if(!itemCountList.isEmpty()){
                for (AppItemCountDTO appItemCount : itemCountList){
                    if(appItemCount.getItemLocation().equals(bettingItemStr)){
                        appItemCountDTO.setConsecutive(appItemCount.getConsecutive() + 1);
                    }
                }
            }

            // 更新连中
            appGameItemService.updateConsecutive(appItemCountDTO);
            nowItemCountList.add(appItemCountDTO);
        }

        redisCache.setCacheObject("G:GameCount:" + gameId, JSON.toJSONString(nowItemCountList));
    }

    @DSTransactional
    public List<String> gameBettingTask(Long classId, Long gameId, String gameDate, String bettingItem) throws Exception {
        List<String> userIds = new ArrayList<>();
        List<AppGameBetting> list = appGameBettingService.getIsWinning(classId, gameId, gameDate, 0);

        if(list == null || list.isEmpty()){
            return userIds;
        }

        for (int i = 0; i < list.size(); i++) {
            AppGameBetting appGameBetting = list.get(i);
            appGameBetting.setUpdateTime(new Date());

            String [] bettingItems = bettingItem.split(",");
            List<String> bettingItemsList = Arrays.asList(bettingItems);

            double bettingAmount = appGameBetting.getBettingAmount() * appGameBetting.getBettingMultiple();
            bettingAmount = new BigDecimal(bettingAmount + "").setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();

            if(appGameBetting.getBettingGameType() == 0){
                if(!bettingItemsList.contains(appGameBetting.getBettingItem())){
                    appGameBetting.setIsWinning(2);
                    appGameBettingService.updateById(appGameBetting);
                    continue;
                }
            }else if(appGameBetting.getBettingGameType() == 1 || appGameBetting.getBettingGameType() == 2){
                List<AppGameItemBettingVO> itemList = JSON.parseArray(appGameBetting.getBettingItem(), AppGameItemBettingVO.class);
                if(itemList == null || itemList.isEmpty()){
                    appGameBetting.setIsWinning(2);
                    appGameBettingService.updateById(appGameBetting);
                    continue;
                }
                List<String> bettingItemList = itemList.stream().map(AppGameItemBettingVO::getBettingItem).collect(Collectors.toList());
                boolean isWinning = false;
                for (int j = 0; j < bettingItemList.size(); j++) {
                    String bettingItemStr = bettingItemList.get(j);
                    if(bettingItemsList.contains(bettingItemStr)){
                        isWinning = true;
                        break;
                    }
                }

                if(!isWinning){
                    appGameBetting.setIsWinning(2);
                    appGameBettingService.updateById(appGameBetting);
                    continue;
                }

                if(appGameBetting.getBettingGameType() == 2){
                    for (int k = 0; k < itemList.size(); k++) {
                        AppGameItemBettingVO appGameItemBettingVO = itemList.get(k);
                        if(bettingItemsList.contains(appGameItemBettingVO.getBettingItem())){
                            bettingAmount = appGameBetting.getBettingAmount() * appGameItemBettingVO.getBettingMultiple();
                            bettingAmount = new BigDecimal(bettingAmount + "").setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
                            break;
                        }
                    }
                }
            }

            AppUser appUser = appUserService.selectAppUserByUserid(appGameBetting.getUserId());
            if(appUser == null){
                appGameBetting.setIsWinning(1);
                appGameBettingService.updateById(appGameBetting);
                continue;
            }

            // 添加推送消息用户
            String userId = appUser.getUserid() + "";
            if(!userIds.contains(userId)){
                userIds.add(userId);
            }

            // 更新用户余额
            //if(appGameBetting.getBettingType() == 0){
            //    appUser.setDiamondCoin(appUser.getDiamondCoin() + bettingAmount );
            //    appUser.setDiamondCoinTotal(appUser.getDiamondCoinCashTotal() + bettingAmount);
            //    appUser.setDiamondCoinCash(appUser.getDiamondCoinCash() + bettingAmount);
            // 更新用户金币
            //}else{
            //    appUser.setCoin(appUser.getCoin() + bettingAmount);
            //        if(appUser.getRole() == 1){
            //            appUser.setCoinCash(appUser.getCoinCash() + bettingAmount);
            //        }
            //}

            //appUserService.updateAppUser(appUser);

            //redisCache.deleteObject("U:UserInfo:" + appUser.getUserid());

            appGameBetting.setIsWinning(1);
            appGameBettingService.updateById(appGameBetting);

            FinTranRecord finTranRecord = new FinTranRecord();

            //finTranRecord.setAfterCoin(appUser.getCoin());
            //finTranRecord.setAfterDiamondCoin(appUser.getDiamondCoin());

            if(appGameBetting.getBettingType() == 0){
                finTranRecord.setCurrencyType(4);
                finTranRecord.setDiamondCoinChange(bettingAmount);
                finTranRecord.setCoinChange(0.00);
            }else{
                finTranRecord.setCurrencyType(2);
                finTranRecord.setCoinChange(bettingAmount);
                finTranRecord.setDiamondCoinChange(0.00);
            }

            finTranRecord.setAfterMoney(0.00);
            finTranRecord.setMoneyChange(0.00);

            finTranRecord.setAfterTicket(0.00);
            finTranRecord.setTicketChange(0.00);

            finTranRecord.setToUid(appUser.getUserid());
            finTranRecord.setUid(appUser.getUserid());

            finTranRecord.setSceneId1(0L);
            finTranRecord.setSceneId2(null);
            finTranRecord.setSceneType(0L);

            finTranRecord.setTranGroupId(appGameBetting.getId());

            if(appGameBetting.getBettingType() == 0){
                finTranRecord.setTranType1(FinTranType1.U_Income_Coin_Balance.getType());
            }else{
                finTranRecord.setTranType1(FinTranType1.U_Income_Coin.getType());
            }

            finTranRecord.setTranType2(FinTranType2.GAME_REWARD.getType());
            finTranRecord.setTranType3(FinTranType3.CHARGE_WIN_GAME.getType());

            finTranRecord.setRemarks("游戏中奖");

            finTranRecord.setConsumptionCoin(appGameBetting.getBettingAmount());
            finTranRecord.setConsumptionMoney(0.00);
            finTranRecord.setCommissionRelatedUid(0L);
            finTranRecord.setAgentId(appUser.getAgentId());

            finTranRecord.setCreateTime(new Date());

            finTranRecord.setFromUid(appGameBetting.getUserId());
            finTranRecord.setGoodsId(0L);
            finTranRecord.setGuildId(0L);
            finTranRecord.setManagerCoId(0L);
            finTranRecord.setManagerId(0L);

            finTranRecord.setPerc(0.00);
            finTranRecord.setProId(0L);
            finTranRecord.setProCount(0L);

            finTranRecord.setOrderId(appGameBetting.getId());
            //finTranRecordService.insertFinTranRecord(finTranRecord);
            appUserService.updateUserAmount(finTranRecord);
        }
        return userIds;
    }

    public void sendMsg(List<String> userIdList){
        if(userIdList == null || userIdList.isEmpty()){
            return;
        }

        JSONObject paramJson = new JSONObject();
        paramJson.put("type", "UserSystemNotify");
        paramJson.put("subType", "UserRefreshBalance");
        paramJson.put("content", JSONObject.parseObject("{'msg':'刷新余额'}"));

        List<String> sendUsers = new ArrayList<>();
        if(userIdList.size() > 500){
            for(String userId : userIdList){
                if(sendUsers.size() >= 500){
                    TencentCloudImUtil.imPushBatchSendMsg(sendUsers, paramJson.toString());
                    sendUsers.clear();
                }
                sendUsers.add(userId);
            }
            // 剩余不超过500
            if(!sendUsers.isEmpty()){
                TencentCloudImUtil.imPushBatchSendMsg(sendUsers, paramJson.toString());
            }
        }else{
            TencentCloudImUtil.imPushBatchSendMsg(userIdList, paramJson.toString());
        }
    }
}
