package com.game.business.controller;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.game.business.domain.*;
import com.game.business.task.AppAgentGameBettingTask;
import com.game.business.vo.*;
import com.game.business.service.*;
import com.game.common.annotation.Anonymous;
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.controller.BaseController;
import com.game.common.core.domain.HttpRet;
import com.game.common.core.domain.HttpRetPageArr;
import com.game.common.core.redis.RedisCache;
import com.game.common.utils.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/business/betting")
@Api(value = "AppGameBettingController", description = "游戏投注接口", tags = {"游戏投注、查询记录等"})
public class AppGameBettingController extends BaseController{

    @Autowired
    private IAppGameBettingService appGameBettingService;

    @Autowired
    private IAppGameService appGameService;

    @Autowired
    private IAppGameClassifyService appGameClassifyService;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private IFinTranRecordService finTranRecordService;

    @Autowired
    private IAppGameLotteryService appGameLotteryService;

    @Autowired
    private IAppGameItemService appGameItemService;

    @Autowired
    private AppAgentGameBettingTask appAgentGameBettingTask;

    @Autowired
    private RedisCache redisCache;

    /**
     * 下注
     */
    @Anonymous
    @PostMapping(value = "/create")
    @ApiOperation(value = "游戏下注", notes = "游戏下注")
    @DSTransactional
    public HttpRet<Double> betting(@RequestBody AppGameBetting gameBetting) throws Exception {

        if(gameBetting.getClassId() == null){
            return HttpRet.fail("游戏平台ID为空。");
        }

        if(gameBetting.getGameId() == null){
            return HttpRet.fail("游戏ID为空。");
        }

        if(gameBetting.getUserId()== null){
            return HttpRet.fail("用户ID为空。");
        }

        if(gameBetting.getBettingGameType() == null){
            gameBetting.setBettingGameType(0);
        }

        AppGameClassify appGameClassify = appGameClassifyService.selectAppGameClassifyById(gameBetting.getClassId());
        if(appGameClassify == null){
            return HttpRet.fail("游戏平台不存在。");
        }

        AppGame appGame = appGameService.selectAppGameById(gameBetting.getGameId());
        if(appGame == null){
            return HttpRet.fail("游戏不存在。");
        }

        if(appGame.getStatus() == 0){
            return HttpRet.fail("游戏已下线，无法下单。");
        }

        if(StringUtils.isBlank(appGame.getGameDate())){
            return HttpRet.fail("游戏期号不存在，无法下单。");
        }

        if(StringUtils.isBlank(appGame.getGameTime())){
            return HttpRet.fail("游戏已封盘，无法下单。");
        }

        if(!appGame.getGameTime().contains(":")){
            return HttpRet.fail("游戏已封盘，无法下单。");
        }

        // 单选
        if(gameBetting.getBettingGameType() == 0){
            AppGameItem appGameItem = appGameItemService.selectAppGameItemByGameIdAndItemLocation(appGame.getId(), gameBetting.getBettingItem());
            if(appGameItem == null){
                return HttpRet.fail("游戏选项不存在，无法下单。");
            }

            gameBetting.setBettingMultiple(Double.parseDouble(appGameItem.getItemMultiple() + ""));
        // 多选
        }else if(gameBetting.getBettingGameType() == 1 || gameBetting.getBettingGameType() == 2){
            List<AppGameItemBettingVO> itemList = JSON.parseArray(gameBetting.getBettingItem(), AppGameItemBettingVO.class);
            if(itemList == null || itemList.isEmpty()){
                return HttpRet.fail("游戏选项不存在，无法下单。");
            }
            for(AppGameItemBettingVO item : itemList){
                AppGameItem appGameItem = appGameItemService.selectAppGameItemByGameIdAndItemLocation(appGame.getId(), item.getBettingItem());
                if(appGameItem == null){
                    return HttpRet.fail("游戏选项不存在，无法下单。");
                }
            }
            // 写死的倍数
            if(gameBetting.getBettingGameType() == 1){
                gameBetting.setBettingMultiple(getMultiple(itemList.size()));
            }
        }

//        String[] timeArry = appGame.getGameTime().substring(0, 5).split(":");
//        int m = Integer.parseInt(timeArry[1]);
//
//        if(m <= 10){
//            return HttpRet.fail("游戏已封盘，无法下单。");
//        }

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

        if(count > 0){
            return HttpRet.fail("游戏已开奖，无法下单。");
        }

        AppUser appUser = appUserService.selectAppUserByUserid(gameBetting.getUserId());

        if(appUser == null){
            return HttpRet.fail("用户不存在。");
        }

        if(gameBetting.getBettingType() == 0){

            // 获取用户金额，判断投注金额是否大于余额
            if(gameBetting.getBettingAmount() > appUser.getDiamondCoin()){
                return HttpRet.fail("余额不足，投注失败。");
            }

            // 更新用户余额
            //appUser.setDiamondCoin(appUser.getDiamondCoin() - gameBetting.getBettingAmount());
            //appUser.setDiamondCoinTotal(appUser.getDiamondCoinTotal() - gameBetting.getBettingAmount());
            //appUser.setDiamondCoinCash(appUser.getDiamondCoinCash() - gameBetting.getBettingAmount());
        }else{

            // 获取用户金额，判断投注金额是否大于余额
            if(gameBetting.getBettingAmount() > appUser.getCoin()){
                return HttpRet.fail("金币不足，投注失败。");
            }

            //appUser.setCoin(appUser.getCoin() - gameBetting.getBettingAmount());

            // 判断不可提现金币是否满足扣款
            //if(gameBetting.getBettingAmount() > (appUser.getCoin() - appUser.getCoinCash())){
            //    appUser.setCoinCash(gameBetting.getBettingAmount() - (appUser.getCoin() - appUser.getCoinCash()));
            //}
        }

        //appUserService.updateAppUser(appUser);

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

        gameBetting.setGameDate(appGame.getGameDate());
        gameBetting.setIsLive(0);
        if(gameBetting.getLiveRoomId() != null && gameBetting.getLiveRoomId() > 0 && gameBetting.getLiveUserId() != null && gameBetting.getLiveUserId() > 0){
            gameBetting.setIsLive(1);
        }

        gameBetting.setCreateTime(new Date());
        // 插入投注记录
        appGameBettingService.save(gameBetting);

        FinTranRecord finTranRecord = new FinTranRecord();

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

        if(gameBetting.getBettingType() == 0){
            finTranRecord.setCurrencyType(4);
            finTranRecord.setDiamondCoinChange(gameBetting.getBettingAmount() * -1);
            finTranRecord.setCoinChange(0.00);
        }else{
            finTranRecord.setCurrencyType(2);
            finTranRecord.setCoinChange(gameBetting.getBettingAmount() * -1);
            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(gameBetting.getId());
        finTranRecord.setTranType1(FinTranType1.U_Outcome_Balance.getType());
        finTranRecord.setTranType2(FinTranType2.CONSUM_GAME.getType());
        finTranRecord.setTranType3(FinTranType3.CONSUM_GAME_ANCHOR_ZHUANPAN.getType());

        finTranRecord.setRemarks("游戏下注");

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

        finTranRecord.setCreateTime(new Date());

        finTranRecord.setFromUid(appUser.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(gameBetting.getId());
        //finTranRecordService.insertFinTranRecord(finTranRecord);
        appUserService.updateUserAmount(finTranRecord);

        // 分佣
        if(gameBetting.getBettingType() == 0){
            appAgentGameBettingTask.agentGameBettingTask(gameBetting);
        }

        return HttpRet.success("下注成功", appUser.getDiamondCoin());
    }

    /**
     * 游戏输赢统计
     */
    @Anonymous
    @PostMapping(value = "/count")
    @ApiOperation(value = "游戏输赢统计（首页）", notes = "游戏输赢统计（首页）")
    public HttpRet<AppGameBettingCountVO> getCount(@RequestParam(name = "strDate") String strDate, @RequestParam(name = "userId") Long userId, @RequestParam(name = "bettingType") Integer bettingType)
    {

        if(bettingType == null){
            bettingType = 0;
        }
        AppGameBettingCountVO appGameBettingCountDTO = new AppGameBettingCountVO();
        List<AppGame> gameList = appGameService.selectAppGameList(new AppGame());

        if(gameList == null || gameList.isEmpty()){
            return HttpRet.success("查询成功",appGameBettingCountDTO);
        }

        List<AppGameBettingDetailsCountVO> countList = appGameBettingService.getCount(strDate, userId, bettingType);
        if(countList == null){
            countList = new ArrayList<>();
        }
        Map<Long, List<AppGameBettingDetailsCountVO>> idGameMap = countList.stream().collect(Collectors.groupingBy(AppGameBettingDetailsCountVO::getGameId));

        List<AppGameBettingDetailsCountVO> newList = new ArrayList<>();
        double orderAmount = 0.00;
        double winAmount = 0.00;
        double loseAmount = 0.00;
        for (int i = 0; i < gameList.size(); i++) {
            AppGame appGame = gameList.get(i);
            AppGameBettingDetailsCountVO appGameBettingDetailsCountDTO = new AppGameBettingDetailsCountVO();
            appGameBettingDetailsCountDTO.setBettingType(bettingType);
            appGameBettingDetailsCountDTO.setGameId(appGame.getId());
            appGameBettingDetailsCountDTO.setGameName(appGame.getName());
            appGameBettingDetailsCountDTO.setLogoUrl(appGame.getLogoUrl());
            appGameBettingDetailsCountDTO.setGamePath(appGame.getGamePath());
            if(idGameMap.containsKey(appGame.getId())){
                AppGameBettingDetailsCountVO dbAppGameBettingDetailsCount = idGameMap.get(appGame.getId()).get(0);
                appGameBettingDetailsCountDTO.setBettingCount(dbAppGameBettingDetailsCount.getBettingCount());
                appGameBettingDetailsCountDTO.setOrderAmount(dbAppGameBettingDetailsCount.getOrderAmount());
                appGameBettingDetailsCountDTO.setWinAmount(dbAppGameBettingDetailsCount.getWinAmount());
                appGameBettingDetailsCountDTO.setLoseAmount(dbAppGameBettingDetailsCount.getLoseAmount());
                orderAmount += dbAppGameBettingDetailsCount.getOrderAmount();
                winAmount += dbAppGameBettingDetailsCount.getWinAmount();
                loseAmount += dbAppGameBettingDetailsCount.getLoseAmount();
            }else{
                appGameBettingDetailsCountDTO.setBettingCount(0);
                appGameBettingDetailsCountDTO.setOrderAmount(0.00);
                appGameBettingDetailsCountDTO.setWinAmount(0.00);
                appGameBettingDetailsCountDTO.setLoseAmount(0.00);
            }
            newList.add(appGameBettingDetailsCountDTO);
        }
        appGameBettingCountDTO.setOrderAmount(orderAmount);
        appGameBettingCountDTO.setWinAmount(winAmount);
        appGameBettingCountDTO.setLoseAmount(loseAmount);
        appGameBettingCountDTO.setList(newList);
        return HttpRet.success("查询成功", appGameBettingCountDTO);
    }

    /**
     * 游戏输赢详情列表
     */
    @Anonymous
    @PostMapping(value = "/listByGameId")
    @ApiOperation(value = "游戏输赢统计（详情）", notes = "游戏输赢统计（详情）")
    public HttpRetPageArr<AppGameBettingVO> getListByGameId(@RequestParam(name = "gameId") Long gameId, @RequestParam(name = "userId") Long userId,
                                                            @RequestParam(name = "isWinning") Integer isWinning, @RequestParam(name = "strDate", required = false) String strDate
                                                            ,@RequestParam(name = "bettingType", required = false) Integer bettingType)
    {
        startPage();
        List<AppGameBetting> list = appGameBettingService.selectListByGameId(gameId, userId, isWinning, strDate, bettingType);
        List<AppGameBettingVO> resultList = new ArrayList<>();
        if(list != null && !list.isEmpty()){
            AppGameItem appGameItem = new AppGameItem();
            appGameItem.setGameId(gameId);
            List<AppGameItem> itemList = appGameItemService.selectAppGameItemList(appGameItem);
            Map<String, List<AppGameItem>> codeItmeMap = itemList.stream().collect(Collectors.groupingBy(AppGameItem::getItemLocation));
            for (int i = 0; i <list.size(); i++) {
                AppGameBetting appGameBetting  = list.get(i);
                AppGameBettingVO appGameBettingVO = new AppGameBettingVO();
                BeanUtils.copyProperties(appGameBetting, appGameBettingVO);

                if(StringUtils.isNotBlank(appGameBettingVO.getBettingItem())){
                    if(codeItmeMap.containsKey(appGameBettingVO.getBettingItem())){
                        appGameBettingVO.setItemName(codeItmeMap.get(appGameBettingVO.getBettingItem()).get(0).getItemName());
                    }
                }
                resultList.add(appGameBettingVO);
            }
        }
        return HttpRetPageArr.success("查询成功",getDataTable(resultList));
    }


    /**
     * 游戏投注记录
     */
    @Anonymous
    @PostMapping(value = "/listHistory")
    @ApiOperation(value = "游戏投注记录", notes = "游戏投注记录")
    public HttpRetPageArr<AppUserGameBettingCountVO> listHistory(@RequestParam(name = "gameId") Long gameId , @RequestParam(name = "bettingType", required = false) Integer bettingType
            , @RequestParam(name = "bettingGameType", required = false) Integer bettingGameType)
    {
        startPage();
        Long userId = SecurityUtils.getUserId();
        List<AppUserGameBettingCountVO> list = appGameBettingService.getUserCount(gameId, userId, bettingType);

        if(bettingGameType == null){
            bettingGameType = 0;
        }
        if(bettingType == null){
            bettingType = 0;
        }

        if(list != null && !list.isEmpty()){

            if(bettingGameType == 0){
                for (int i = 0; i < list.size(); i++) {
                    AppUserGameBettingCountVO appUserGameBettingCountVO = list.get(i);
                    List<AppUserGameBettingDetailsCountVO> detailsCountVOList = appGameBettingService.getUserBettingItemCount(gameId, appUserGameBettingCountVO.getGameDate(), userId, bettingType);
                    if(detailsCountVOList == null){
                        detailsCountVOList  = new ArrayList<>();
                    }
                    appUserGameBettingCountVO.setDetailsCountVOList(detailsCountVOList);
                }
            }else if(bettingGameType == 1){
                for (int i = 0; i < list.size(); i++) {

                    AppUserGameBettingCountVO appUserGameBettingCountVO = list.get(i);
                    List<AppGameBetting> bettingList = appGameBettingService.getUserBettingItem(gameId, appUserGameBettingCountVO.getGameDate(), userId, bettingType);
                    if(bettingList == null){
                        bettingList  = new ArrayList<>();
                    }
                    Map<String, AppUserGameBettingDetailsCountVO> itemMap = new HashMap<>();
                    for (int j = 0; j < bettingList.size(); j++) {
                        AppGameBetting appGameBetting =  bettingList.get(j);

                        List<AppGameItemBettingVO> itemList = JSON.parseArray(appGameBetting.getBettingItem(), AppGameItemBettingVO.class);

                        for(AppGameItemBettingVO item : itemList){
                            if(itemMap.containsKey(item.getBettingItem())){
                                AppUserGameBettingDetailsCountVO appUserGameBettingDetailsCountVO = itemMap.get(item.getBettingItem());
                                appUserGameBettingDetailsCountVO.setOrderAmount(appUserGameBettingDetailsCountVO.getOrderAmount() + item.getBettingAmount());
                                if(appGameBetting.getIsWinning() == 1){
                                    if(item.getBettingItem().equals(appUserGameBettingCountVO.getGameLotterySucc())) {
                                        appUserGameBettingDetailsCountVO.setWinAmount(appUserGameBettingDetailsCountVO.getWinAmount() + (appGameBetting.getBettingAmount() * appGameBetting.getBettingMultiple()));
                                    }
                                }else if(appGameBetting.getIsWinning() == 2){
                                    appUserGameBettingDetailsCountVO.setLoseAmount(appUserGameBettingDetailsCountVO.getLoseAmount() + item.getBettingAmount());
                                }
                                itemMap.put(item.getBettingItem(), appUserGameBettingDetailsCountVO);
                            }else{
                                AppUserGameBettingDetailsCountVO appUserGameBettingDetailsCountVO = new AppUserGameBettingDetailsCountVO();
                                appUserGameBettingDetailsCountVO.setBettingTtem(item.getBettingItem());
                                appUserGameBettingDetailsCountVO.setOrderAmount(item.getBettingAmount());
                                if(appGameBetting.getIsWinning() == 1){
                                    if(item.getBettingItem().equals(appUserGameBettingCountVO.getGameLotterySucc())){
                                        appUserGameBettingDetailsCountVO.setWinAmount(appGameBetting.getBettingAmount() * appGameBetting.getBettingMultiple());
                                    }
                                }else if(appGameBetting.getIsWinning() == 2){
                                    appUserGameBettingDetailsCountVO.setLoseAmount(item.getBettingAmount());
                                }
                                itemMap.put(item.getBettingItem(), appUserGameBettingDetailsCountVO);
                            }
                        }
                    }
                    List<AppUserGameBettingDetailsCountVO> detailsCountVOList = new ArrayList<>();
                    Set<String> set = itemMap.keySet();
                    Iterator<String> iterator = set.iterator();
                    while (iterator.hasNext()){
                        AppUserGameBettingDetailsCountVO appUserGameBettingDetailsCountVO = itemMap.get(iterator.next());
                        detailsCountVOList.add(appUserGameBettingDetailsCountVO);
                    }
                    appUserGameBettingCountVO.setDetailsCountVOList(detailsCountVOList);
                }
            }
        }
        return HttpRetPageArr.success("查询成功",getDataTable(list));
    }

    private double getMultiple(int size){
        double itemMultiple;
        switch (size){
            case 1:
                itemMultiple = 8.5;
                break;
            case 2:
                itemMultiple = 4.0;
                break;
            case 3:
                itemMultiple = 2.0;
                break;
            default:
                itemMultiple = 1.0;
        }
        return itemMultiple;
    }
}
