package com.YuyeTech.HeartRate.game.levelInfo.controller;

import com.YuyeTech.HeartRate.VO.ResultVO;
import com.YuyeTech.HeartRate.dataobject.*;
import com.YuyeTech.HeartRate.dto.LevelConditionDTO;
import com.YuyeTech.HeartRate.dto.LevelHonorDTO;
import com.YuyeTech.HeartRate.enums.ResultEnum;
import com.YuyeTech.HeartRate.exception.UserException;
import com.YuyeTech.HeartRate.game.levelInfo.projo.LevelJump;
import com.YuyeTech.HeartRate.game.levelInfo.service.LevelConditionService;
import com.YuyeTech.HeartRate.game.levelInfo.service.LevelHonorService;
import com.YuyeTech.HeartRate.game.levelInfo.service.LevelJumpService;
import com.YuyeTech.HeartRate.service.*;
import com.YuyeTech.HeartRate.utils.RSAUtils;
import com.YuyeTech.HeartRate.utils.ResultVOUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author:slambb
 * @date:2021/8/4
 */
@RestController
@RequestMapping("/level")
@Slf4j
public class LevelController {

    @Autowired
    private LevelJumpService levelJumpService;

    @Autowired
    private LevelConditionService levelConditionService;

    @Autowired
    private UserLevelService userLevelService;

    @Autowired
    private UserWalletsService userWalletsService;

    @Autowired
    private UserRewardService userRewardService;

    @Autowired
    private LevelHonorService levelHonorService;


    @Value("${RSA.friendId.publicKey}")
    private String friendIdPublicKey;
    @Value("${RSA.friendId.privateKey}")
    private String friendIdPrivateKey;

    /**
     * 获取levelJump关卡列表
     *
     * @param userId
     * @return
     */
    @GetMapping("/getLevelJumpList")
    public ResultVO getLevelJumpList(@RequestParam(value = "userId") String userId) {
        Map map = levelJumpService.findLevelJumpsAll(userId);
        return ResultVOUtil.success(map);
    }

    /**
     * 获取全部关卡列表
     *
     * @param userId
     * @return
     */
    @GetMapping("/getLevelList")
    public ResultVO getLevelList(@RequestParam(value = "userId") String userId) {
        Map map = levelJumpService.findLevels(userId);
        return ResultVOUtil.success(map);
    }

    /**
     * 过关调用此处，第一次过关，添加对应的信息
     * 只处理levelJump信息
     *
     * @param userId
     * @param eventId 关卡id
     * @return
     */
    @GetMapping("/passTheLevel")
    @Transactional(rollbackFor = Exception.class)
    public ResultVO passTheLevel(@RequestParam(value = "userId") String userId,
                                 //@RequestParam(value = "levelType") Integer eventType,
                                 @RequestParam(value = "levelId") Integer eventId) {

        // todo 后面看是否需要处理判断过关条件
        // todo 判断是否存在关卡
        LevelJump levelJump = levelJumpService.findById(eventId);
        if (levelJump == null){
            return ResultVOUtil.error(ResultEnum.LEVEL_ERROR.getCode(),ResultEnum.LEVEL_ERROR.getMessage());
        }
        //根据id和类型获取关卡信息
        UserLevel userLevel = userLevelService.findByUserIdAndEventType(userId, levelJump.getType());

        if (userLevel == null) {
            userLevel = new UserLevel();
            userLevel.setUserId(userId);
            userLevel.setCreateTime(new Date());
            //1 代表 levelJump
            userLevel.setEventType(levelJump.getType());
            userLevel.setPassedState(eventId.toString());
            //本身已解锁的默认不用记录解锁
            userLevel.setUnlockState("");
            userLevelService.saveUserLevel(userLevel);
        } else {
            //存在数据。默认是第二次过关
            String passed = userLevel.getPassedState();
            if (passed.length() > 0) {
                List<Integer> passedStateList = Pattern.compile(",").splitAsStream(passed).map((x) -> Integer.parseInt(x))
                        .collect(Collectors.toList());
                if (!passedStateList.contains(eventId)) {
                    passed = passed.concat("," + eventId);
                    userLevel.setPassedState(passed);
                    userLevelService.saveUserLevel(userLevel);
                }
            } else {
                userLevel.setPassedState(eventId.toString());
                userLevelService.saveUserLevel(userLevel);
            }

        }
        //todo 过关后，发放对应奖励，金币，钻石和荣誉，等等。

        Map map = new HashMap();
        UserReward userReward = userRewardService.findByUserIdAndEventId(userId, eventId);
        //todo 暂时吧跳绳和拳击奖励放一起
        if (levelJump.getType().equals(1) || levelJump.getType().equals(2)) {
            //LevelJump levelJump = levelJumpService.findById(eventId);
            LevelHonorDTO levelHonorDTO = levelHonorService.findByHonorType(levelJump.getRewardHonor());
            if (userReward == null) {
                userReward = new UserReward();
                userReward.setUserId(userId);
                userReward.setCreateTime(new Date());
                userReward.setEventId(levelJump.getId());
                userReward.setEventName(levelJump.getName());
                userReward.setEventType(levelJump.getType());
                userReward.setEventState(1);
                userReward.setPlayCount(1);
            } else {
                //如果存在数据，+1次数
                userReward.setPlayCount(userReward.getPlayCount() + 1);
            }
            userReward.setGold(levelJump.getRewardGold());
            userReward.setDiamond(levelJump.getRewardDiamond());
            userReward.setHonor(levelJump.getRewardHonor());
            userReward.setHonorName(levelHonorDTO.getName());
            userReward.setHonorExplain(levelHonorDTO.getExplain());
            userReward.setHonorUrl(levelHonorDTO.getUrl());

            userRewardService.saveUserReward(userReward);
            //如果需要奖励
            //todo 奖励用户相应信息
            UserWallets userWallets = userWalletsService.modifyGoldAndDiamondInUserWallets(userId, levelJump.getRewardGold(), levelJump.getRewardDiamond(), true);

            map.put("rewardHonor", levelHonorDTO);
            map.put("rewardGold", levelJump.getRewardGold());
            map.put("rewardDiamond", levelJump.getRewardDiamond());
            //返回一个钱包情况
            map.put("gold", userWallets.getGold());
            map.put("diamond", userWallets.getDiamond());

        }else{
            //todo
        }


        map.put("unlockState", userLevel.getUnlockState());
        map.put("passedState", userLevel.getPassedState());
        return ResultVOUtil.success(map);
    }

    @GetMapping("/unlockLevel")
    public ResultVO UnlockLevel(@RequestParam(value = "userId") String userId,
                                //@RequestParam(value = "numberType") Integer numberType,
                                //@RequestParam(value = "levelType") Integer eventType,
                                @RequestParam(value = "levelId") Integer eventId) {

        // todo 判断是否存在关卡
        LevelJump levelJump = levelJumpService.findById(eventId);
        if (levelJump == null){
            return ResultVOUtil.error(ResultEnum.LEVEL_ERROR.getCode(),ResultEnum.LEVEL_ERROR.getMessage());
        }

        try {
            //0自动解锁
            //单人模式解锁条件：1上一关，2金币，3钻石，
            //双人模式解锁条件：单人模式解锁*(4躲猫猫,5恐龙,6醉拳，7拳霸，8蹦迪，9大威天龙）
            //1.第一步先判断除了金币和钻石的条件。目前除了2,3.其余的只有一个条件需要判断
            // 单人条件下，只需要判断上一关的是否已经解锁
            // 拿到用户记录的关卡数据 levelType = levelJump(1)，
            UserLevel userLevel = userLevelService.findByUserIdAndEventType(userId, levelJump.getType());
            if (userLevel == null) {
                //提示必须通过第一个自动解锁的关卡。这样才能记录
                return ResultVOUtil.error(ResultEnum.MUST_PASS_FIRST_LEVEL.getCode(), ResultEnum.MUST_PASS_FIRST_LEVEL.getMessage());
            }
            List<Integer> _passedStateList = Pattern.compile(",").splitAsStream(userLevel.getPassedState()).map((x) -> Integer.parseInt(x))
                    .collect(Collectors.toList());
            List<Integer> _unlockStateList = Pattern.compile(",").splitAsStream(userLevel.getUnlockState()).map((x) -> Integer.parseInt(x))
                    .collect(Collectors.toList());
            //先处理关卡数据
            if (_unlockStateList.size() > 0) {
                if (!_unlockStateList.contains(eventId)) {
                    String _unlock = userLevel.getUnlockState().concat("," + eventId);
                    userLevel.setUnlockState(_unlock);
                }
            } else {
                userLevel.setUnlockState(eventId.toString());
            }

            LevelJump curLevelJump = null;
            Boolean isPassed = false;
            List<Map> _unlockMapList = new ArrayList<>();
            //单人条件下判断上一关一个条件
            if (levelJump.getNumberType().equals(1)) {
                List<LevelJump> levelJumpList = levelJumpService.findLevelJumpsByNumberTypeAndType(levelJump.getNumberType(),levelJump.getType(), Sort.Direction.ASC);
                for (int i = 0; i < levelJumpList.size(); i++) {
                    curLevelJump = levelJumpList.get(i);
                    if (curLevelJump.getId().equals(eventId)) {
                        //如果需要解锁的关卡，如果判断上一关是否通过，并且需要i>0
                        isPassed = _passedStateList.contains(levelJumpList.get(i - 1).getId());
                        break;
                    }
                }

            } else if (levelJump.getNumberType().equals(2)) {
                //2人模式下，处理条件是需要判断单人模式下对应的关卡是否解锁
                //todo 拿到当前条件下得limitLevel
                curLevelJump = levelJumpService.findById(eventId);
                List<LevelConditionDTO> _lcDTOList = levelConditionService.findByConditionUnlockIn(curLevelJump.getConditionUnlock());

                Map _itemMap = new HashMap();
                for (int j = 0; j < _lcDTOList.size(); j++) {
                    LevelConditionDTO levelConditionDTO = _lcDTOList.get(j);
                    if (levelConditionDTO.getLimitLevel() != null
                            && !levelConditionDTO.getLimitLevel().equals(2)
                            && !levelConditionDTO.getLimitLevel().equals(3)) {
                        //判断是否解锁
                        _itemMap.put("levelId", levelConditionDTO.getLimitType());
                        _itemMap.put("explain", levelConditionDTO.getExplain());
                        _unlockMapList.add(_itemMap);
                        isPassed = _unlockStateList.contains(levelConditionDTO.getLimitLevel());
                        break;
                    }
                }
            }

            //如果已经解锁。判断是否需要金币
            if (isPassed) {
                if (curLevelJump.getConsumeGold() == 0 && curLevelJump.getConsumeDiamond() == 0) {
                    //如果不存在扣金币和钻石的情况。即直接解锁
                    //记录关卡信息
                    userLevelService.saveUserLevel(userLevel);
                    Map map = new HashMap();
//                    map.put("userLevel",userLevel);
                    return ResultVOUtil.success(map);
                } else {
                    //如果需要扣除金币或者钻石
                    //todo 获取用户钱包信息
                    UserWallets userWallets = userWalletsService.modifyGoldAndDiamondInUserWallets(userId, curLevelJump.getConsumeGold(), curLevelJump.getConsumeDiamond(), false);

                    //扣费后记录关卡信息
                    userLevelService.saveUserLevel(userLevel);
                    Map map = new HashMap();
                    map.put("gold", userWallets.getGold());
                    map.put("diamond", userWallets.getDiamond());
//                    map.put("userLevel",userLevel);
                    return ResultVOUtil.success(map);
                }

            } else {
                if (levelJump.getType().equals(1) || levelJump.getType().equals(2)) {
                    //目前levelJump = 1
                    if (levelJump.getNumberType().equals(1)) {
                        return ResultVOUtil.error(ResultEnum.PREVIOUS_LEVEL_NO_PASSED.getCode(), ResultEnum.PREVIOUS_LEVEL_NO_PASSED.getMessage());

                    } else if (levelJump.getNumberType().equals(2)) {
                        return ResultVOUtil.error(ResultEnum.ASSOCIATED_LEVEL_NO_UNLOCKED.getCode(), ResultEnum.ASSOCIATED_LEVEL_NO_UNLOCKED.getMessage(), _unlockMapList);

                    }
                } else {
                    //todo 后续处理不同的eventType，关卡类型
                    return ResultVOUtil.error(ResultEnum.OTHER_LEVEL_NO_UNLOCKED.getCode(), ResultEnum.OTHER_LEVEL_NO_UNLOCKED.getMessage());

                }
            }

            return ResultVOUtil.error(ResultEnum.LEVEL_NO_UNLOCKED.getCode(), ResultEnum.LEVEL_NO_UNLOCKED.getMessage());


        } catch (UserException e) {
            return ResultVOUtil.error(e.getCode(), e.getMessage());
        }
    }


    /**
     * pk 关卡奖励
     */
    @GetMapping("/pkLevelReward")
    @Transactional(rollbackFor = Exception.class)
    public ResultVO passTheLevel(@RequestParam(value = "userId") String userId,
                                 @RequestParam(value = "friendId") String friendRSA,
                                 @RequestParam(value = "isMyWin") Boolean isMyWin,
                                 @RequestParam(value = "levelType") Integer eventType,
                                 @RequestParam(value = "levelId") Integer eventId) throws InvalidKeySpecException, NoSuchAlgorithmException {
        //不管谁获胜。都处理通过userId的关卡
        //根据id和类型获取关卡信息
        UserLevel userLevel = userLevelService.findByUserIdAndEventType(userId, eventType);

        if (userLevel == null) {
            userLevel = new UserLevel();
            userLevel.setUserId(userId);
            userLevel.setCreateTime(new Date());
            //1 代表 levelJump
            userLevel.setEventType(eventType);
            userLevel.setPassedState(eventId.toString());
            //本身已解锁的默认不用记录解锁
            userLevel.setUnlockState("");
            userLevelService.saveUserLevel(userLevel);
        } else {
            //存在数据。默认是第二次过关
            String passed = userLevel.getPassedState();
            if (passed.length() > 0) {
                List<Integer> passedStateList = Pattern.compile(",").splitAsStream(passed).map((x) -> Integer.parseInt(x))
                        .collect(Collectors.toList());
                if (!passedStateList.contains(eventId)) {
                    passed = passed.concat("," + eventId);
                    userLevel.setPassedState(passed);
                    userLevelService.saveUserLevel(userLevel);
                }
            } else {
                userLevel.setPassedState(eventId.toString());
                userLevelService.saveUserLevel(userLevel);
            }

        }
        //todo pk后，发放对应奖励，金币，钻石和荣誉，等等。
        Map map = new HashMap();
        String decFriendId = RSAUtils.privateDecrypt(friendRSA, RSAUtils.getPrivateKey(friendIdPrivateKey));

        String curId = isMyWin ? userId : decFriendId;
        UserReward userReward = userRewardService.findByUserIdAndEventId(curId, eventId);
        if (eventType.equals(1)) {
            LevelJump levelJump = levelJumpService.findById(eventId);
            LevelHonorDTO levelHonorDTO = levelHonorService.findByHonorType(levelJump.getRewardHonor());
            if (userReward == null) {
                userReward = new UserReward();
                userReward.setUserId(curId);
                userReward.setCreateTime(new Date());
                userReward.setEventId(levelJump.getId());
                userReward.setEventName(levelJump.getName());
                userReward.setEventType(eventType);
                userReward.setEventState(1);
                userReward.setPlayCount(1);
            } else {
                //如果存在数据，+1次数
                userReward.setPlayCount(userReward.getPlayCount() + 1);
            }
            userReward.setGold(levelJump.getRewardGold());
            userReward.setDiamond(levelJump.getRewardDiamond());
            userReward.setHonor(levelJump.getRewardHonor());
            userReward.setHonorName(levelHonorDTO.getName());
            userReward.setHonorExplain(levelHonorDTO.getExplain());
            userReward.setHonorUrl(levelHonorDTO.getUrl());

            userRewardService.saveUserReward(userReward);

            //如果需要奖励
            //todo 奖励用户相应信息
            UserWallets userWallets = userWalletsService.modifyGoldAndDiamondInUserWallets(curId, levelJump.getRewardGold(), levelJump.getRewardDiamond(), true);

            map.put("rewardHonor", levelHonorDTO);
            map.put("rewardGold", levelJump.getRewardGold());
            map.put("rewardDiamond", levelJump.getRewardDiamond());
            //如果是自己赢的，返回给当前客户端一个自己用户的钱包情况
            if (isMyWin) {
                map.put("gold", userWallets.getGold());
                map.put("diamond", userWallets.getDiamond());
            }

        }
        map.put("unlockState", userLevel.getUnlockState());
        map.put("passedState", userLevel.getPassedState());
        return ResultVOUtil.success(map);
    }

}
