package com.td.boss.game.comsnbfreeze.controller;

import com.td.boss.common.controller.*;
import com.td.boss.common.pojo.Result;
import com.td.boss.config.enums.ResultEnum;
import com.td.boss.game.comcntorder.service.ComCntOrderService;
import com.td.boss.game.comcntorder.vo.ComCntOrderVo;
import com.td.boss.game.comconfigland.pojo.ComConfigLand;
import com.td.boss.game.comconfigland.service.ComConfigLandService;
import com.td.boss.game.comconfigland.vo.ComConfigLandVo;
import com.td.boss.game.commallseed.pojo.ComMallSeed;
import com.td.boss.game.commallseed.service.ComMallSeedService;
import com.td.boss.game.commallseed.vo.ComMallSeedVo;
import com.td.boss.game.complayergoods.pojo.ComPlayerGoods;
import com.td.boss.game.complayergoods.service.ComPlayerGoodsService;
import com.td.boss.game.complayergoods.vo.ComPlayerGoodsSimpleVo;
import com.td.boss.game.complayergoods.vo.ComPlayerGoodsVo;
import com.td.boss.game.complayerland.pojo.ComPlayerLand;
import com.td.boss.game.complayerland.service.ComPlayerLandService;
import com.td.boss.game.complayerland.vo.ComPlayerLandSimpleVo;
import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
import com.td.boss.game.comsnbfreeze.pojo.ComSnbFreeze;
import com.td.boss.game.comsnbfreeze.vo.ComSnbFreezeSimpleVo;
import com.td.boss.game.comsnbfreeze.vo.ComSnbFreezeVo;
import com.td.boss.game.comsnbfreeze.service.ComSnbFreezeService;
import com.td.boss.game.comsnbtran.service.ComSnbTranService;
import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
import com.td.boss.game.comusers.service.ComUsersService;
import com.td.boss.game.comusers.vo.ComUsersVo;
import com.td.boss.util.CopyUtil;
import com.td.boss.util.DateUtil;
import com.td.boss.util.RedisData;
import com.td.boss.util.RedisLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;

import static com.td.boss.util.MD5Util.createSign;

@RestController
@RequestMapping("/game/wallet/")
@Slf4j
public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, ComSnbFreeze, String> {

    @Autowired
    private ComUsersService comUsersService;

    @Autowired
    private ComSnbFreezeService comSnbFreezeService;

    @Autowired
    private ComCntOrderService comCntOrderService;

    @Autowired
    private ComPlayerGoodsService comPlayerGoodsService;

    @Autowired
    private ComMallSeedService comMallSeedService;

    @Autowired
    private ComPlayerLandService comPlayerLandService;

    @Autowired
    private ComConfigLandService comConfigLandService;

    @Autowired
    private ComSnbTranService comSnbTranService;


    @Autowired
    private RedisLock redisLock;


    /**
     * 获取用户神农呗 snb，前端用户调用
     *
     * @param userId
     * @return
     */
    @GetMapping("getSNB")
    public Result<Map> getSNBFunction(@RequestParam(value = "userId") String userId) {
        //log.info(userId);
        ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
        Map map = new HashMap();
        map.put("SNB", comUsersVo.getSnb());
        return Result.of(map);
    }

    /**
     * 这里获取游戏的SNB和冻结用户钱包
     *
     * @param id 账户ID
     * @return
     */
    @PostMapping("getSNBAndFreeze")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Result<Map> getSNBAndFreezeFunction(
            @RequestParam(value = "id") Integer id,
            @RequestParam(value = "snbAmount") Integer snbAmount,
            @RequestParam(value = "sign") String sign
    ) {
        Map map = new HashMap();
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("id", id);
        parameters.put("snbAmount", snbAmount);
        String _sign = createSign(parameters);

        log.info("getSNBAndFreezeFunction:" + parameters.toString());

        if (!_sign.equals(sign)) {
            map.put("msg", "签名参数错误");
            //return Result.of(map, false, ResultEnum.WALLET_SNB_SIGN_ERROR.getMessage(), ResultEnum.WALLET_SNB_SIGN_ERROR.getCode());
            return Result.of(map);
        }

        //拿出用户对应的数据
        ComUsersVo comUsersVo = comUsersService.findByUserId(id.toString());
        if (comUsersVo.getSnb() < snbAmount) {
            map.put("msg", "账户snb不足");
            //WALLET_SNB_INSUFFICIENT_QUANTITY(602,"snb不足以支付！")
            //return Result.of(map, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
            return Result.of(map);
        }
        //如果数量够，写入修改对应操作
        Integer _beforeSnb = comUsersVo.getSnb();
        Integer _snb = comUsersVo.getSnb() - snbAmount;
        comUsersVo.setSnb(_snb);
        //todo snb冻结加锁
        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
        String _redisKey = "SNB_SAVE_" + comUsersVo.getUserId();
        try {
            // 防止重复操作
            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
                map.put("msg", "冻结操作：SNB保存失败，请重试此操作！");
                return Result.of(map);
            }
            comUsersService.save(comUsersVo);
            redisLock.unlock(_redisKey, String.valueOf(time));
        }catch (Exception e){
            redisLock.unlock(_redisKey, String.valueOf(time));
            map.put("msg", "保存账户数据失败！");
            return Result.of(map);
        }

        //记录操作的snb，
        ComSnbFreezeVo entityVo = new ComSnbFreezeVo();
        entityVo.setUserId(id.toString());
        entityVo.setSnb(snbAmount);
        entityVo.setFreeze(1);
        entityVo.setIsSuccess(0);//0默认交易不成功
        entityVo.setSnbDescribe("SNB兑换CNT时候添加的冻结数据");
        Result<ComSnbFreezeVo> result = comSnbFreezeService.save(entityVo);
        map.put("snbFreeze", CopyUtil.copy(result.getData(), ComSnbFreezeSimpleVo.class));


        /**
         * todo 冻结的snb数据记录
         */
        ComSnbTranVo _snbTran = new ComSnbTranVo();
        //记录兑换id
        _snbTran.setTranId(entityVo.getId());
        _snbTran.setUserId(id.toString());
        _snbTran.setTranName("冻结操作");
        _snbTran.setTranType(1);
        _snbTran.setTranAmount(snbAmount); //此数量会操作背包记录
        _snbTran.setTranPrice(snbAmount);
        //"出售果实价格：" + comFruitVo.getPriceSnb() + "，数量：" + amount
        _snbTran.setTranDescribe("新兑换cnt时候冻结的用户数据");
        _snbTran.setIsAdd(0);//减少
        _snbTran.setBeforeSnb(_beforeSnb);
        _snbTran.setTranSnb(snbAmount);
        _snbTran.setAfterSnb(_snb);

        _snbTran.setTranAmountPart(0d);
        _snbTran.setTranSnbPart(0d);
        _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
        _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());

        comSnbTranService.save(_snbTran);

        return Result.of(map);
    }

    /**
     * 解除冻结用户钱包
     *
     * @param snbId
     * @return
     */
    @PostMapping("setSNBAndUnfreeze")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Result<Map> setSNBAndUnfreezeFunction(
            @RequestParam(value = "snbId") String snbId,
            @RequestParam(value = "isSuccess") Integer isSuccess,
            @RequestParam(value = "sign") String sign) {
        Map map = new HashMap();
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("snbId", snbId);
        parameters.put("isSuccess", isSuccess);
        String _sign = createSign(parameters);

        log.info("setSNBAndUnfreezeFunction:" + parameters.toString());
        if (!_sign.equals(sign)) {
            map.put("msg", "签名参数错误");
            //return Result.of(map, false, ResultEnum.WALLET_SNB_SIGN_ERROR.getMessage(), ResultEnum.WALLET_SNB_SIGN_ERROR.getCode());
            return Result.of(map);
        }

        ComSnbFreezeVo comSnbFreezeVo = comSnbFreezeService.findById(snbId);
        if (!comSnbFreezeVo.getIsSuccess().equals(0)) {
            //交易状态是0才可以进行下一步操作
            //WALLET_SNB_SUCCESS_NOT_ZERO(603,"snb不可操作"),
            map.put("isSuccess", comSnbFreezeVo.getIsSuccess());
            map.put("msg", "交易状态不为0");
            //return Result.of(map, false, ResultEnum.WALLET_SNB_SUCCESS_NOT_ZERO.getMessage(), ResultEnum.WALLET_SNB_SUCCESS_NOT_ZERO.getCode());
            return Result.of(map);
        }

        if (isSuccess.equals(1)) {
            //1 成功
            comSnbFreezeVo.setIsSuccess(1);
            comSnbFreezeVo.setFreeze(0);
            map.put("msg", "交易成功");
            comSnbFreezeService.save(comSnbFreezeVo);
        } else {
            //交易失败，返回snb给用户
            ComUsersVo comUsersVo = comUsersService.findByUserId(comSnbFreezeVo.getUserId());
            Integer _beforeSnb = comUsersVo.getSnb();
            Integer _snb = comUsersVo.getSnb() + comSnbFreezeVo.getSnb();
            comUsersVo.setSnb(_snb);
            //todo snb冻结加锁
            long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
            String _redisKey = "SNB_SAVE_" + comUsersVo.getUserId();
            try {
                // 防止重复操作
                if (!redisLock.lock(_redisKey, String.valueOf(time))) {
                    map.put("msg", "冻结操作：SNB保存失败，请重试此操作！");
                    return Result.of(map);
                }
                comUsersService.save(comUsersVo);
                redisLock.unlock(_redisKey, String.valueOf(time));
            }catch (Exception e){
                redisLock.unlock(_redisKey, String.valueOf(time));
                map.put("msg", "保存账户数据失败！");
                return Result.of(map);
            }

            map.put("SNB", comUsersVo.getSnb());
            //记录交易转态
            comSnbFreezeVo.setIsSuccess(2);
            map.put("msg", "交易失败，返回SNB给用户成功");
            comSnbFreezeService.save(comSnbFreezeVo);
            /**
             * todo 解冻交易失败 snb数据记录
             */
            ComSnbTranVo _snbTran = new ComSnbTranVo();
            //记录兑换id
            _snbTran.setTranId(comSnbFreezeVo.getId());
            _snbTran.setUserId(comSnbFreezeVo.getUserId());
            _snbTran.setTranName("解冻操作");
            _snbTran.setTranType(2);
            _snbTran.setTranAmount(comSnbFreezeVo.getSnb()); //此数量会操作背包记录
            _snbTran.setTranPrice(comSnbFreezeVo.getSnb());
            //"出售果实价格：" + comFruitVo.getPriceSnb() + "，数量：" + amount
            _snbTran.setTranDescribe("新兑换cnt失败时候解冻的用户数据");
            _snbTran.setIsAdd(1);//增加
            _snbTran.setBeforeSnb(_beforeSnb);
            _snbTran.setTranSnb(comSnbFreezeVo.getSnb());
            _snbTran.setAfterSnb(_snb);

            _snbTran.setTranAmountPart(0d);
            _snbTran.setTranSnbPart(0d);
            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
            comSnbTranService.save(_snbTran);
        }

        map.put("isSuccess", comSnbFreezeVo.getIsSuccess());
        map.put("freeze", comSnbFreezeVo.getFreeze());

        return Result.of(map);
    }


    /**
     * "id": 1, // 用户ID
     * "address": "TDw6xsVnDJWsdRBLkWAwXbv4hE2X2JQs5z", // 用户地址
     * "pay_type": 1, // 支付类型，1土地租凭
     * "pay_amount": "100.00", // 支付数额
     * "tx_hash": "15200dd5a3f32c7046e2d5b9e346f2e200d311c85463af77bbeb7ff632d69230", // 交易hash，需要唯一校验，防止重复计算
     * "sign": "4609A6B4998E5B44C5F6AA30DBFEDD37" // 参数签名，需要校验防止参数被篡改
     *
     * @return
     */
    @PostMapping("cntPlayback")
    @ResponseBody
    public Result<Map> onCNTPlayBack(@RequestParam(value = "id") Integer id,
                                     @RequestParam(value = "address") String address,
                                     @RequestParam(value = "pay_type") Integer pay_type,
                                     @RequestParam(value = "pay_amount") String pay_amount,
                                     @RequestParam(value = "tx_hash") String tx_hash,
                                     @RequestParam(value = "item_type") String item_type,
                                     @RequestParam(value = "sign") String sign) {
        Map<String, Object> result = new HashMap<>();

        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("id", id);
        parameters.put("address", address);
        parameters.put("pay_type", pay_type);
        parameters.put("pay_amount", pay_amount);
        parameters.put("tx_hash", tx_hash);
        parameters.put("item_type", item_type);
        String _sign = createSign(parameters);

        log.info("onCNTPlayBack:" + parameters.toString());

        if (_sign.equals(sign)) {

            ComCntOrderVo comCntOrderVo = comCntOrderService.findByTx(tx_hash);
            //记录CNT 订单
            if (comCntOrderVo == null) {
                comCntOrderVo = new ComCntOrderVo();
            }
            comCntOrderVo.setAddress(address);
            comCntOrderVo.setUserId(id.toString());
            comCntOrderVo.setPayAmount(pay_amount);
            comCntOrderVo.setItemType(item_type);
            comCntOrderVo.setPayType(pay_type);
            comCntOrderVo.setTxHash(tx_hash);
            if (comCntOrderVo.getPayType().equals(1) //3个月
            ) {
                comCntOrderVo.setCntDescribe("购买土地租凭");

                // 处理租赁,下面要走校验，防止修改数据
                //  目前是根据CNT走设置
                //todo 土地操作修改 比如倍数+id = 1or12 2or12 3or12
                String[] itemArray = item_type.split("or");
                Integer playCycle = Integer.parseInt(itemArray[0]); //土地周期，比如3个月，1年,5年等
                Integer configLandId = Integer.parseInt(itemArray[1]); //itemType

                //根据土地config id查找，对应ConfigLandId ,
                ComConfigLand comConfigLand = comConfigLandService.findById(configLandId);

                //如果土地等于不能初始化，或者已经种植，不能进行购买
                if (comConfigLand.getIsInit().equals(0) || comConfigLand.getIsPlant().equals(1)) {
                    comCntOrderVo.setCntDescribe("非法操作:" + ResultEnum.LAND_DATA_ERROR.getMessage());
                    comCntOrderService.save(comCntOrderVo);
                    result.put("msg", "非法操作:" + ResultEnum.LAND_DATA_ERROR.getMessage());
                    //return Result.of(result, false, ResultEnum.LAND_DATA_ERROR.getMessage(), ResultEnum.LAND_DATA_ERROR.getCode());
                    return Result.of(result);
                }
                //能通过交易的都是未租赁的
                ComPlayerLand comPlayerLand = comPlayerLandService.findByUserIdAndLandId(id.toString(), configLandId);
                Boolean isNewPlant = false;
                if (comPlayerLand == null) {
                    //创建新土地
                    comPlayerLand = new ComPlayerLand();
                    comPlayerLand.setConfigLandId(comConfigLand.getId());
                    comPlayerLand.setUserId(id.toString());
                    comPlayerLand.setName(comConfigLand.getName());
                    //todo 续租问题，如果用户续租，保留之前的状态
                    //初始化一下未种植参数
                    comPlayerLand.setIsPlant(0);
                    comPlayerLand.setCreateTime(new Date());
                    comPlayerLand.setPlantSteal(1);
                    isNewPlant = true;
                }
                //todo 可能续租
                //else {

                //土地已经租赁，非法操作
                //if (comPlayerLand.getIsLease().equals(1)) {
                //    comCntOrderVo.setCntDescribe("非法操作:" + ResultEnum.LAND_IS_LEASE.getMessage());
                //    comCntOrderService.save(comCntOrderVo);
                //    result.put("msg", "非法操作:" + ResultEnum.LAND_IS_LEASE.getMessage());
                //    //return Result.of(result, false, ResultEnum.LAND_IS_LEASE.getMessage(), ResultEnum.LAND_IS_LEASE.getCode());
                //    return Result.of(result);
                //}
                //}
                // 假如返回的是 三个月700CNT,一年2500CNT，5年5000CNT
                Double _backCNT = Double.parseDouble(pay_amount);

                //用约定来处理 土地类型和倍数  1000 A 12 ,组合的就是 1000A12


                if (playCycle.equals(1)) {//_backCNT % 700 == 0
                    int multiple = (int) Math.floor(_backCNT / 700);
                    comPlayerLand.setLandDescribe("当前租赁三个月，消耗" + _backCNT + "CNT,倍数为：" + multiple);
                    comPlayerLand.setLeaseMultiple(multiple);
                    comPlayerLand.setLeaseDate(1);
                    //设置租赁日期
                    if (isNewPlant) {
                        comPlayerLand.setLeaseTime(DateUtil.getNowDateAddMonth(3));
                    } else {
                        comPlayerLand.setLeaseTime(DateUtil.getOldDateAddMonth(comPlayerLand.getLeaseTime(), 3));
                    }


                } else if (playCycle.equals(2)) {//_backCNT % 2500 == 0
                    int multiple = (int) Math.floor(_backCNT / 2500);
                    comPlayerLand.setLandDescribe("当前租赁一年，消耗" + _backCNT + "CNT,倍数为：" + multiple);
                    comPlayerLand.setLeaseMultiple(multiple);
                    comPlayerLand.setLeaseDate(2);
                    //设置租赁日期
                    if (isNewPlant) {
                        comPlayerLand.setLeaseTime(DateUtil.getNowDateAddYear(1));
                    } else {
                        comPlayerLand.setLeaseTime(DateUtil.getOldDateAddYear(comPlayerLand.getLeaseTime(), 1));
                    }

                } else if (playCycle.equals(3)) { //_backCNT % 5000 == 0
                    int multiple = (int) Math.floor(_backCNT / 5000);
                    comPlayerLand.setLandDescribe("当前租赁5年，消耗" + _backCNT + "CNT,倍数为：" + multiple);
                    comPlayerLand.setLeaseMultiple(multiple);
                    comPlayerLand.setLeaseDate(3);
                    //设置租赁日期
                    //comPlayerLand.setLeaseTime(DateUtil.getNowDateAddYear(5));
                    if (isNewPlant) {
                        comPlayerLand.setLeaseTime(DateUtil.getNowDateAddYear(5));
                    } else {
                        comPlayerLand.setLeaseTime(DateUtil.getOldDateAddYear(comPlayerLand.getLeaseTime(), 5));
                    }

                } else {
                    //不存在此CNT交易数值
                    comCntOrderVo.setCntDescribe("非法操作:购买土地的playCycle:" + playCycle);
                    comCntOrderService.save(comCntOrderVo);
                    result.put("msg", "非法操作:CNT交易数值不是设定的数据!");
                    return Result.of(result);
                }
                //租赁土地
                comPlayerLand.setIsLease(1);
                comPlayerLand.setUpdateTime(new Date());
                //记录一下租赁费用
                comPlayerLand.setRentalExpenses(_backCNT);
                //ComPlayerLandVo comPlayerLandVo = CopyUtil.copy(comPlayerLand, ComPlayerLandVo.class);
                comPlayerLandService.AddComPlayerLand(comPlayerLand);
                //返回土地对象
                //前端轮询或者通过webSocket 发送通知
                result.put("leaseLand", CopyUtil.copy(comPlayerLand, ComPlayerLandSimpleVo.class));

            } else if (comCntOrderVo.getPayType().equals(2)) {
                comCntOrderVo.setCntDescribe("自然灾害防护");
            } else if (comCntOrderVo.getPayType().equals(3)) {
                comCntOrderVo.setCntDescribe("野兽防护");
            } else if (comCntOrderVo.getPayType().equals(4)) {

                // 验证种子价格是否和服务器一样，不一样判定非法操作
                //     假如拿到的 支付 _backCNT = 99; 然后 种子 price = 99.00
                Double _backCNT = Double.parseDouble(pay_amount);
                // 处理itemType,种子id ,获取种子类型，设置种子不同的数据
                // todo 直接处理种子id
                Integer itemType =  Integer.parseInt(item_type);
                ComMallSeedVo seedVo = comMallSeedService.findById(itemType);
                if (seedVo == null) {
                    comCntOrderVo.setCntDescribe("非法操作:所修改的种子不存在服务器中！当前购买种子id:" + itemType);
                    comCntOrderService.save(comCntOrderVo);
                    result.put("msg", "非法操作:所修改的种子不存在服务器中!");
                    return Result.of(result);
                }

                if (!seedVo.getPriceCnt().equals(_backCNT) && _backCNT % seedVo.getPriceCnt() != 0) {
                    //如果价格 不和种子相当，也不是种子的倍数
                    comCntOrderVo.setCntDescribe("非法操作:价格不和种子相当，也不是种子的倍数！当前购买种子的CNT价格:" + _backCNT + ".种子的价格：" + seedVo.getPriceCnt());
                    comCntOrderService.save(comCntOrderVo);
                    result.put("msg", "订单非法操作，已记录相关信息！");
                    return Result.of(result);
                }


                //合法操作记录到仓库中
                comCntOrderVo.setCntDescribe("购买种子");
                ComPlayerGoods entityVo = comPlayerGoodsService.findByUserIdAndIndexAndType(id.toString(), itemType, 0);

                //这里计算一个购买种子的数量，用种子除去单价

                int _paySeedAmount = (int) (_backCNT / seedVo.getPriceCnt());
                if (entityVo == null) {
                    //创建一个新种子
                    entityVo = new ComPlayerGoods();
                    entityVo.setGoodsIndex(itemType);
                    entityVo.setGoodsType(0);
                    entityVo.setUserId(id.toString());
                    entityVo.setAmount(_paySeedAmount);
                    entityVo.setName(seedVo.getName());
                    entityVo.setAmountPart(0d);
                    entityVo.setPictureName(seedVo.getPicture());
                } else {
                    Integer _amount = entityVo.getAmount() + _paySeedAmount;
                    entityVo.setAmount(_amount);
                }
                /** 购买成功后，记录到仓库中*/
                ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(entityVo, ComPlayerGoodsVo.class);
                comPlayerGoodsService.save(comPlayerGoodsVo);
                result.put("seed", CopyUtil.copy(entityVo, ComPlayerGoodsSimpleVo.class));
            }
            comCntOrderService.save(comCntOrderVo);
            result.put("msg", "保存订单成功！");
            return Result.of(result);
        } else {
            //参数校验错误
            result.put("msg", "保存订单失败！");
            return Result.of(result, false, ResultEnum.WALLET_CNT_PLAY_ERROR.getMessage(), ResultEnum.WALLET_CNT_PLAY_ERROR.getCode());
        }

    }
}
