package com.td.WaDa.game.complayerdog.controller;

import com.td.WaDa.common.controller.*;
import com.td.WaDa.common.pojo.Result;
import com.td.WaDa.config.enums.ResultEnum;
import com.td.WaDa.game.commallfood.service.ComMallFoodService;
import com.td.WaDa.game.commallfood.vo.ComMallFoodVo;
import com.td.WaDa.game.commallother.service.ComMallOtherService;
import com.td.WaDa.game.commallother.vo.ComMallOtherSimpleVo;
import com.td.WaDa.game.commallother.vo.ComMallOtherVo;
import com.td.WaDa.game.complayerdog.pojo.ComPlayerDog;
import com.td.WaDa.game.complayerdog.vo.ComPlayerDogSimpleVo;
import com.td.WaDa.game.complayerdog.vo.ComPlayerDogVo;
import com.td.WaDa.game.complayerdog.service.ComPlayerDogService;
import com.td.WaDa.game.comsnbtran.service.ComSnbTranService;
import com.td.WaDa.game.comsnbtran.vo.ComSnbTranVo;
import com.td.WaDa.game.comusers.service.ComUsersService;
import com.td.WaDa.game.comusers.vo.ComUsersVo;
import com.td.WaDa.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

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

@RestController
@Slf4j
@RequestMapping("/game/comPlayerDog/")
public class ComPlayerDogController extends CommonController<ComPlayerDogVo, ComPlayerDog, String> {
    @Autowired
    private ComPlayerDogService comPlayerDogService;

    @Autowired
    private ComMallOtherService comMallOtherService;

    @Autowired
    private ComUsersService comUsersService;

    @Autowired
    private ComSnbTranService comSnbTranService;

    @Autowired
    private ComMallFoodService comMallFoodService;

    @Autowired
    private RedisLock redisLock;

    /**
     * 买狗和打狗棒
     *
     * @param userId
     * @param mallOtherId
     * @return
     */
    @PostMapping("addEquipment")
    @Transactional(rollbackFor = Exception.class)
    public Result<Map> addEquipmentFunction(@RequestParam(value = "userId") String userId,
                                            @RequestParam(value = "mallOtherId") Integer mallOtherId) {

        if(!mallOtherId.equals(1)&&!mallOtherId.equals(2)){
            return Result.of(null, false, ResultEnum.MALL_ID_LIMIT.getMessage(), ResultEnum.MALL_ID_LIMIT.getCode());
        }

        Map map = new HashMap();
        //需要redis 加锁
        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
        String _redisKey = "SNB_SAVE_" + userId;
        try {
            ComMallOtherVo comMallOtherVo = comMallOtherService.get(mallOtherId).getData();
            if (comMallOtherVo == null) {
                return Result.of(null, false, ResultEnum.MALL_OTHER_IS_NULL.getMessage(), ResultEnum.MALL_OTHER_IS_NULL.getCode());
            }
            ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, comMallOtherVo.getOtherType());
            if (comPlayerDog != null) {
                //todo 计算狗和打狗棒是否到期,未到期给提示，到期下面直接给新的计算时间
                long _runDay = DateUtil.getDays(DateUtil.getNowDate().getTime() - comPlayerDog.getEffectiveStartTime().getTime());
                int _remainingDay = comPlayerDog.getEffectiveDay() - (int) _runDay;
                if (_remainingDay > 0) {
                    return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_HAVE.getMessage(), ResultEnum.PLAYER_OTHER_IS_HAVE.getCode());
                }
            }
            // 防止重复操作
            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
                return Result.of(null, false, ResultEnum.REDIS_IS_LOCK.getMessage(), ResultEnum.REDIS_IS_LOCK.getCode());
            }

            ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
            if(comUsersVo.getSnb()<=0){
                return Result.of(map, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
            }

            Double _allSnb = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
            //如果有snb，扣除对应的snb
            Integer _allSnbMaxInt = (int) Math.floor(_allSnb);
            if (_allSnbMaxInt < comMallOtherVo.getPriceSnb()) {
                return Result.of(null, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
            }
            /**
             * todo 购买装备时候snb变动
             */
            ComSnbTranVo _snbTran = new ComSnbTranVo();
            _snbTran.setBeforeSnb(comUsersVo.getSnb());
            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());

            Integer _tranSnb = _allSnbMaxInt - comMallOtherVo.getPriceSnb();
            comUsersVo.setSnb(_tranSnb);
            Double _SnbPart = DoubleUtil.sub(_allSnb, Math.floor(_allSnb));
            comUsersVo.setSnbPart(_SnbPart);
            //记录修改的数据
            comUsersService.save(comUsersVo);

            //记录交易数据
            _snbTran.setTranId(mallOtherId.toString());
            _snbTran.setUserId(userId);
            if (comMallOtherVo.getOtherType().equals(0)) {
                _snbTran.setTranName("购买狗");
                _snbTran.setTranType(5);
                _snbTran.setTranDescribe("购买了一只狗");
            } else if (comMallOtherVo.getOtherType().equals(1)) {
                _snbTran.setTranName("购买棒子");
                _snbTran.setTranType(6);
                _snbTran.setTranDescribe("购买了一根打狗棒");
            }
            _snbTran.setTranAmount(1);
            _snbTran.setTranAmountPart(0d);
            _snbTran.setTranPrice(comMallOtherVo.getPriceSnb());
            _snbTran.setIsAdd(0);//减少
            _snbTran.setTranSnb(comMallOtherVo.getPriceSnb());
            _snbTran.setTranSnbPart(0d);
            _snbTran.setAfterSnb(comUsersVo.getSnb());
            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
            comSnbTranService.save(_snbTran);

            Date _nowDate = DateUtil.getNowDate();
            if (comPlayerDog == null) {
                comPlayerDog = new ComPlayerDog();
                comPlayerDog.setOtherIndex(mallOtherId);
                comPlayerDog.setOtherType(comMallOtherVo.getOtherType());
                comPlayerDog.setUserId(userId);
                comPlayerDog.setAmount(1);
                comPlayerDog.setAmountPart(0d);
                comPlayerDog.setEffectiveDay(comMallOtherVo.getEffectiveDay());
                comPlayerDog.setEffectiveStartTime(_nowDate);
                comPlayerDog.setConsumption(0);//狗的消耗品是狗粮
                comPlayerDog.setConsumptionUpdate(_nowDate);
                //记录一个最大值
                comPlayerDog.setTotalConsumption(0);
                comPlayerDog.setIsShow(1);//默认显示
                comPlayerDog.setStartShowTime(_nowDate);
            } else {
                //重置新狗的有效时间
                comPlayerDog.setEffectiveDay(comMallOtherVo.getEffectiveDay());
                comPlayerDog.setEffectiveStartTime(_nowDate);
            }
            comPlayerDogService.save(CopyUtil.copy(comPlayerDog, ComPlayerDogVo.class));

            //加入是否显示判断
            long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
            //隐藏计算
            if (comPlayerDog.getIsShow().equals(0)) {
                //计算双倍的时间
                _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
            }
            long _consumptionHours = DateUtil.getDiffHours(_allTime);
            int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;

            ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
            comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
            comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));

            long _runDay = DateUtil.getDays(_nowDate.getTime() - comPlayerDog.getEffectiveStartTime().getTime());
            int _remainingDay = comPlayerDog.getEffectiveDay() - (int) _runDay;
            comPlayerDogSimpleVo.setRemainingDay(_remainingDay < 0 ? 0 : _remainingDay);
            comPlayerDogSimpleVo.setTotalDay(comPlayerDog.getEffectiveDay());

            redisLock.unlock(_redisKey, String.valueOf(time));

            map.put("equip", comPlayerDogSimpleVo);
            return Result.of(map);
        } catch (Exception e) {
            redisLock.unlock(_redisKey, String.valueOf(time));
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 添加狗粮
     *
     * @param userId
     * @return
     */
    @PostMapping("addFood")
    @Transactional(rollbackFor = Exception.class)
    public Result<Map> addFoodFunction(@RequestParam(value = "userId") String userId,
                                       @RequestParam(value = "foodId") Integer foodId,
                                       @RequestParam(value = "buyAmount", defaultValue = "1") Integer buyAmount) {

        if(!foodId.equals(1)&&!foodId.equals(2)){
            return Result.of(null, false, ResultEnum.MALL_FOOD_ID_LIMIT.getMessage(), ResultEnum.MALL_FOOD_ID_LIMIT.getCode());
        }
        //查看用户是否有狗
        ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, 0);
        if (comPlayerDog == null) {
            return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_NULL.getMessage(), ResultEnum.PLAYER_OTHER_IS_NULL.getCode());
        }

        ComMallFoodVo comMallFoodVo = comMallFoodService.get(foodId).getData();
        Map map = new HashMap();
        if (comMallFoodVo == null) {
            map.put("msg", "非法操作:所修改的种子不存在服务器中!");
            return Result.of(map, false, ResultEnum.FOOD_DATA_ERROR.getMessage(), ResultEnum.FOOD_DATA_ERROR.getCode());
        }
        //todo snb加锁
        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
        String _redisKey = "SNB_SAVE_" + userId;
        try {
            //todo snb冻结加锁
            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
                return Result.of(null, false, ResultEnum.SEED_SALE_SAVE_LOCK.getMessage(), ResultEnum.SEED_SALE_SAVE_LOCK.getCode());
            }
            //todo 操作snb数量
            ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
            if(comUsersVo.getSnb()<=0){
                redisLock.unlock(_redisKey, String.valueOf(time));
                return Result.of(map, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
            }

            /**
             * todo 购买狗粮时候snb变动
             */
            ComSnbTranVo _snbTran = new ComSnbTranVo();
            _snbTran.setBeforeSnb(comUsersVo.getSnb());
            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
            //计算
            Double _allSnb = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
            //如果有snb，扣除对应的snb
            Integer _allSnbMaxInt = (int) Math.floor(_allSnb);
            Integer _needPrice = buyAmount * comMallFoodVo.getPriceSnb();
            if (_allSnbMaxInt < _needPrice) {
                return Result.of(null, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
            }
            Integer _tranSnb = _allSnbMaxInt - _needPrice;
            comUsersVo.setSnb(_tranSnb);
            Double _SnbPart = DoubleUtil.sub(_allSnb, Math.floor(_allSnb));
            comUsersVo.setSnbPart(_SnbPart);
            //记录修改的数据
            comUsersService.save(comUsersVo);

            //修改狗的数据
            Date _nowDate = DateUtil.getNowDate();
            //加入是否显示判断
            long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
            //隐藏计算
            if (comPlayerDog.getIsShow().equals(0)) {
                //计算双倍的时间
                _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
                //计算了一次双时间，记录
                comPlayerDog.setStartShowTime(_nowDate);
            }
            long _consumptionHours = DateUtil.getDiffHours(_allTime);
            int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;

            //判断狗粮是否消耗完，未消耗完叠加，消耗完重新设置
            Integer _addWeight = buyAmount * comMallFoodVo.getWeight();
            if (_remainingConsumption < 0) {
                comPlayerDog.setConsumption(_addWeight);
                //记录一个最大值
                comPlayerDog.setTotalConsumption(_addWeight);
            } else {
                comPlayerDog.setConsumption(_remainingConsumption + _addWeight);
                //记录一个最大值,已当前更新为主
                comPlayerDog.setTotalConsumption(_remainingConsumption + _addWeight);
            }

            comPlayerDog.setConsumptionUpdate(_nowDate);
            comPlayerDogService.save(CopyUtil.copy(comPlayerDog, ComPlayerDogVo.class));

            //记录交易数据
            _snbTran.setTranId(foodId.toString());
            _snbTran.setUserId(userId);
            _snbTran.setTranName("购买狗粮");
            _snbTran.setTranType(7);
            _snbTran.setTranDescribe("购买狗粮类型：" + comMallFoodVo.getMallType() + ",Weight:" + comMallFoodVo.getWeight());
            _snbTran.setTranAmount(comMallFoodVo.getWeight());
            _snbTran.setTranAmountPart(0d);
            _snbTran.setTranPrice(comMallFoodVo.getPriceSnb());
            _snbTran.setIsAdd(0);//减少
            _snbTran.setTranSnb(_needPrice);
            _snbTran.setTranSnbPart(0d);
            _snbTran.setAfterSnb(comUsersVo.getSnb());
            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
            comSnbTranService.save(_snbTran);

            redisLock.unlock(_redisKey, String.valueOf(time));

            ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
            comPlayerDogSimpleVo.setRemainingConsumption(comPlayerDog.getConsumption());
            ComMallOtherVo comMallOtherVo = comMallOtherService.get(comPlayerDog.getOtherIndex()).getData();
            comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
            long _runDay = DateUtil.getDays(_nowDate.getTime() - comPlayerDog.getEffectiveStartTime().getTime());
            int _remainingDay = comPlayerDog.getEffectiveDay() - (int) _runDay;
            comPlayerDogSimpleVo.setRemainingDay(_remainingDay < 0 ? 0 : _remainingDay);
            comPlayerDogSimpleVo.setTotalDay(comPlayerDog.getEffectiveDay());

            map.put("dog", comPlayerDogSimpleVo);
            map.put("snb", comUsersVo.getSnb().doubleValue());
            map.put("snbPart", comUsersVo.getSnbPart());

            return Result.of(map);
        } catch (Exception e) {
            redisLock.unlock(_redisKey, String.valueOf(time));
            throw new RuntimeException(e.getMessage());
        }
    }

    @GetMapping("getEquipmentByType")
    public Result<ComPlayerDogSimpleVo> getEquipmentByTypeFunction(@RequestParam(value = "userId") String userId,
                                                                   @RequestParam(value = "type") Integer type) {

        ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, type);
        if (comPlayerDog == null) {
            return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_NULL.getMessage(), ResultEnum.PLAYER_OTHER_IS_NULL.getCode());
        }
        ComMallOtherVo comMallOtherVo = comMallOtherService.get(comPlayerDog.getOtherIndex()).getData();
        if (comMallOtherVo == null) {
            return Result.of(null, false, ResultEnum.MALL_OTHER_IS_NULL.getMessage(), ResultEnum.MALL_OTHER_IS_NULL.getCode());
        }
        Date _nowDate = DateUtil.getNowDate();
        //加入是否显示判断
        long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
        //隐藏计算
        if (comPlayerDog.getIsShow().equals(0)) {
            //计算双倍的时间
            _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
        }
        long _consumptionHours = DateUtil.getDiffHours(_allTime);
        int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;
        ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
        comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
        comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);

        return Result.of(comPlayerDogSimpleVo);
    }

    @GetMapping("getListEquipment")
    public Result<List<ComPlayerDogSimpleVo>> getListEquipmentFunction(@RequestParam(value = "userId") String userId,
                                                                       @RequestParam(value = "otherUserId", required = false) String otherUserId) {

        String currentUserId = userId;
        if (StringUtils.hasText(otherUserId)) {
            currentUserId = otherUserId;
        }


        List<ComPlayerDog> comPlayerDogList = comPlayerDogService.findAllByUserId(currentUserId);
        List<ComPlayerDogSimpleVo> comPlayerDogSimpleVos = new ArrayList<>();

        Date _nowDate = DateUtil.getNowDate();
        comPlayerDogList.stream().map(e -> {
            ComMallOtherVo comMallOtherVo = comMallOtherService.get(e.getOtherIndex()).getData();
            if (comMallOtherVo == null) {
                return null;
            }
            ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(e, ComPlayerDogSimpleVo.class);
            comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
            long _runDay = DateUtil.getDays(_nowDate.getTime() - e.getEffectiveStartTime().getTime());
            int _remainingDay = e.getEffectiveDay() - (int) _runDay;
            comPlayerDogSimpleVo.setRemainingDay(_remainingDay < 0 ? 0 : _remainingDay);
            comPlayerDogSimpleVo.setTotalDay(e.getEffectiveDay());
            //加入是否显示判断
            long _allTime = _nowDate.getTime() - e.getConsumptionUpdate().getTime();
            //隐藏计算
            if (e.getIsShow().equals(0)) {
                //计算双倍的时间
                _allTime = _nowDate.getTime() * 2 - e.getConsumptionUpdate().getTime() - e.getStartShowTime().getTime();
            }
            long _consumptionHours = DateUtil.getDiffHours(_allTime);
            int _remainingConsumption = e.getConsumption() - (int) _consumptionHours;
            comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
            return comPlayerDogSimpleVos.add(comPlayerDogSimpleVo);

        }).collect(Collectors.toList());

        return Result.of(comPlayerDogSimpleVos);
    }


    /**
     * 设置狗的显示状态
     *
     * @param userId
     * @param isShow
     * @return
     */
    @PostMapping("setDogShowState")
    @Transactional(rollbackFor = Exception.class)
    public Result<Map> setDogShowStateFunction(@RequestParam(value = "userId") String userId,
                                               @RequestParam(value = "isShow") Integer isShow) {

        if(!isShow.equals(1)&&!isShow.equals(0)){
            return Result.of(null, false, ResultEnum.DOG_SHOW_STATE_ERROR.getMessage(), ResultEnum.DOG_SHOW_STATE_ERROR.getCode());
        }

        //查看用户是否有狗
        ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, 0);
        if (comPlayerDog == null) {
            return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_NULL.getMessage(), ResultEnum.PLAYER_OTHER_IS_NULL.getCode());
        }
        Map map = new HashMap();
        //todo 判断是否是隐藏属性，更新一次狗的狗粮数据。隐藏需要双倍处理扣除
        //修改狗的数据
        Date _nowDate = DateUtil.getNowDate();
        //加入是否显示判断
        long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
        //隐藏计算
        if (comPlayerDog.getIsShow().equals(0)) {
            //计算双倍的时间
            _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
        }
        long _consumptionHours = DateUtil.getDiffHours(_allTime);
        int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;
        //计算对应的狗粮
        comPlayerDog.setConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
        comPlayerDog.setConsumptionUpdate(_nowDate);
        //更新状态
        comPlayerDog.setIsShow(isShow);
        comPlayerDog.setStartShowTime(_nowDate);
        comPlayerDogService.save(CopyUtil.copy(comPlayerDog, ComPlayerDogVo.class));
        ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
        comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
        ComMallOtherVo comMallOtherVo = comMallOtherService.get(comPlayerDog.getOtherIndex()).getData();
        comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
        map.put("dog", comPlayerDogSimpleVo);
        return Result.of(map);
    }

}
