package com.td.boss.game.complayerland.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.comexplainland.service.ComExplainLandService;
import com.td.boss.game.comexplainland.vo.ComExplainLandVo;
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.ComPlayerGoodsVo;
import com.td.boss.game.complayerland.pojo.ComPlayerLand;
import com.td.boss.game.complayerland.pojo.ComPlayerLandAndCanSteal;
import com.td.boss.game.complayerland.vo.ComPlayerLandAndPlantVo;
import com.td.boss.game.complayerland.vo.ComPlayerLandAndUserInfoVo;
import com.td.boss.game.complayerland.vo.ComPlayerLandSimpleVo;
import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
import com.td.boss.game.complayerland.service.ComPlayerLandService;
import com.td.boss.game.complayerlog.service.ComPlayerLogService;
import com.td.boss.game.complayerlog.vo.ComPlayerLogVo;
import com.td.boss.util.CopyUtil;
import com.td.boss.util.DateUtil;
import com.td.boss.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
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/comPlayerLand/")
public class ComPlayerLandController extends CommonController<ComPlayerLandVo, ComPlayerLand, Integer> {

    @Autowired
    private ComPlayerLandService comPlayerLandService;

    @Autowired
    private ComMallSeedService comMallSeedService;

    @Autowired
    private ComPlayerGoodsService comPlayerGoodsService;

    @Autowired
    private ComPlayerLogService comPlayerLogService;

    @Autowired
    private ComExplainLandService comExplainLandService;


    /**
     * 获取用户土地
     * 新增获取其他玩家用户土地信息，简单区分
     *
     * @param userId
     * @return
     */
    @GetMapping("getList")
    public Result<List<ComPlayerLandAndPlantVo>> getLandFunction(@RequestParam(value = "userId") String userId,
                                                                 @RequestParam(value = "otherUserId", required = false) String otherUserId) {
        String _currentUserId = userId;
        //todo 新增获取其他用户信息
        if (StringUtils.hasText(otherUserId)) {
            _currentUserId = otherUserId;
        }
        log.info("获取土地时候的userId:" + _currentUserId);
        List<ComPlayerLand> comPlayerLands = comPlayerLandService.findAllByUserId(_currentUserId);
        List<ComPlayerLandAndPlantVo> _simpleVoList = CopyUtil.copyList(comPlayerLands, ComPlayerLandAndPlantVo.class);
        List<ComPlayerLandAndPlantVo> _list = new ArrayList<>();

        try {
            _simpleVoList.stream().map(e -> {
                ComPlayerLandAndPlantVo comPlayerLandAndPlantVo = e;
                //todo 返回一个计算的天数和小时，解决跨时区的问题
                //租赁的剩余天数 。 测试：DateUtil.getNowDateAddYear(1).getTime(); DateUtil.getNowDate().getTime()
                Long leaseDaysMill = comPlayerLandAndPlantVo.getLeaseTime().getTime() - DateUtil.getNowDate().getTime();
                //精确到毫秒计算判断时间
                if (leaseDaysMill <= 0) {
                    //todo 1.土地租赁到期，删除土地租赁数据
                    comPlayerLandService.delete(e.getId());
                    //todo 2.把删除的这个土地的数据记录到com_explain_land中去
                    ComExplainLandVo comExplainLandVo = new ComExplainLandVo();
                    comExplainLandVo = CopyUtil.copy(e, ComExplainLandVo.class);
                    comExplainLandVo.setLandId(e.getConfigLandId());
                    comExplainLandVo.setLandCreate(e.getCreateTime());
                    comExplainLandVo.setExplainType(0);
                    comExplainLandVo.setExplainDescribe("获取土地列表时:土地租赁过期回收");
                    comExplainLandVo.setCreateTime(new Date());
                    comExplainLandVo.setUpdateTime(new Date());
                    comExplainLandService.save(comExplainLandVo);
                    //过期了不做后续操作
                    return null;
                }
                //土地时间
                //租赁的总时间 = 租赁时间 - 土地数据的创建时间
                Long leaseAllMill = comPlayerLandAndPlantVo.getLeaseTime().getTime() - comPlayerLandAndPlantVo.getCreateTime().getTime();
                Integer allDays = DateUtil.getDays(leaseAllMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseAllMill).intValue();
                comPlayerLandAndPlantVo.setLeaseDays(allDays);
                Integer leaseDays = DateUtil.getDays(leaseDaysMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseDaysMill).intValue();
                comPlayerLandAndPlantVo.setLeaseDaysRemaining(leaseDays);
                //返回一个租赁时间毫秒
                comPlayerLandAndPlantVo.setLeaseDaysMill(leaseDaysMill);

                // 如果种植了,返回一个种植数据
                if (comPlayerLandAndPlantVo.getIsPlant().equals(1)) {
                    ComMallSeedVo comMallSeedVo = comMallSeedService.findById(comPlayerLandAndPlantVo.getPlantId());
                    comPlayerLandAndPlantVo.setSeedInfo(comMallSeedVo);
                    //种子时间
                    //当前时间 > 种植时间+成熟期  = 说明可以收获了
                    //获取当前时间 - 植物的成熟期 = 收获时间，收获时间 >= 种植时间，即可以收获
                    Date _harvestTime = DateUtil.getNowDateMinusDay(comMallSeedVo.getMaturity());
                    // 两个时间差, 逻辑是_harvestTime 时间慢慢接近种植时间
                    long diff = comPlayerLandAndPlantVo.getPlantStart().getTime() - _harvestTime.getTime();
                    //种植的剩余时间毫秒
                    comPlayerLandAndPlantVo.setPlantDaysMill(diff);
                    if (diff <= 0) {
                        //说明可以收获了
                        comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                        comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
                    } else {
                        comPlayerLandAndPlantVo.setPlantDaysRemaining(DateUtil.getDays(diff).intValue());
                        comPlayerLandAndPlantVo.setPlantHoursRemaining(DateUtil.getHours(diff).intValue());
                    }
                } else {
                    //未种植时候，设置为0
                    comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                    comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
                }

                return _list.add(e);
            }).collect(Collectors.toList());

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return Result.of(_list);
    }


    /**
     * 获取可偷取的土地列表
     * 也可以获取自己的可偷列表
     *
     * @param userId
     * @return 返回的是已经过滤租赁过期但未删除的的列表
     */
    @GetMapping("getCanStealDetailList")
    public Result<List<ComPlayerLandAndPlantVo>> getCanStealListFunction(
                                                                 @RequestParam(value = "userId") String userId,
                                                                 @RequestParam(value = "otherUserId") String otherUserId) {

        List<ComPlayerLandAndCanSteal> comPlayerLands = comPlayerLandService.findCanStealByUserIdAndOtherUserId(userId,otherUserId);
        List<ComPlayerLandAndPlantVo> _simpleVoList = CopyUtil.copyList(comPlayerLands, ComPlayerLandAndPlantVo.class);
        List<ComPlayerLandAndPlantVo> _list = new ArrayList<>();
        try {
            _simpleVoList.stream().map(e -> {
                ComPlayerLandAndPlantVo comPlayerLandAndPlantVo = e;
                //todo 返回一个计算的天数和小时，解决跨时区的问题
                //租赁的剩余天数 。 测试：DateUtil.getNowDateAddYear(1).getTime(); DateUtil.getNowDate().getTime()
                Long leaseDaysMill = comPlayerLandAndPlantVo.getLeaseTime().getTime() - DateUtil.getNowDate().getTime();
                //这里不需要处理租赁过期判断
                //土地时间
                //租赁的总时间 = 租赁时间 - 土地数据的创建时间
                Long leaseAllMill = comPlayerLandAndPlantVo.getLeaseTime().getTime() - comPlayerLandAndPlantVo.getCreateTime().getTime();
                Integer allDays = DateUtil.getDays(leaseAllMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseAllMill).intValue();
                comPlayerLandAndPlantVo.setLeaseDays(allDays);
                Integer leaseDays = DateUtil.getDays(leaseDaysMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseDaysMill).intValue();
                comPlayerLandAndPlantVo.setLeaseDaysRemaining(leaseDays);
                //返回一个租赁时间毫秒
                comPlayerLandAndPlantVo.setLeaseDaysMill(leaseDaysMill);

                // 如果种植了,返回一个种植数据
                if (comPlayerLandAndPlantVo.getIsPlant().equals(1)) {
                    ComMallSeedVo comMallSeedVo = comMallSeedService.findById(comPlayerLandAndPlantVo.getPlantId());
                    comPlayerLandAndPlantVo.setSeedInfo(comMallSeedVo);
                    //种子时间
                    //当前时间 > 种植时间+成熟期  = 说明可以收获了
                    //获取当前时间 - 植物的成熟期 = 收获时间，收获时间 >= 种植时间，即可以收获
                    Date _harvestTime = DateUtil.getNowDateMinusDay(comMallSeedVo.getMaturity());
                    // 两个时间差, 逻辑是_harvestTime 时间慢慢接近种植时间
                    long diff = comPlayerLandAndPlantVo.getPlantStart().getTime() - _harvestTime.getTime();
                    //种植的剩余时间毫秒
                    comPlayerLandAndPlantVo.setPlantDaysMill(diff);
                    if (diff <= 0) {
                        //说明可以收获了
                        comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                        comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
                    } else {
                        comPlayerLandAndPlantVo.setPlantDaysRemaining(DateUtil.getDays(diff).intValue());
                        comPlayerLandAndPlantVo.setPlantHoursRemaining(DateUtil.getHours(diff).intValue());
                    }
                } else {
                    //未种植时候，设置为0
                    comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                    comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
                }

                return _list.add(e);
            }).collect(Collectors.toList());

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return Result.of(_list);
    }


    /**
     * 获取租赁土地状态，如果webSocket未通，
     * 使用轮询方法查询更新租赁状态
     *
     * @param userId
     * @return
     */
    @GetMapping("getState")
    public Result<ComPlayerLandSimpleVo> getStateFunction(
            @RequestParam(value = "userId") String userId,
            @RequestParam(value = "landId") Integer landId
    ) {

        ComPlayerLand comPlayerLand = comPlayerLandService.findByUserIdAndLandId(userId, landId);
        //土地数据不存在
        if (comPlayerLand == null) {
            return Result.of(null, false, ResultEnum.LAND_DATA_ERROR.getMessage(), ResultEnum.LAND_DATA_ERROR.getCode());
        }
        ComPlayerLandSimpleVo comPlayerLandSimpleVo = CopyUtil.copy(comPlayerLand, ComPlayerLandSimpleVo.class);
        //todo 返回一个计算的天数和小时，解决跨时区的问题
        //租赁的剩余天数
        Long leaseDaysMill = comPlayerLandSimpleVo.getLeaseTime().getTime() - DateUtil.getNowDate().getTime();
        //租赁的剩余天数
        //精确到毫秒计算判断时间，先判断一下是否过期，和购买土地时候轮询通用，这里不影响购买土地
        if (leaseDaysMill <= 0) {
            //todo 1.土地租赁到期，删除土地租赁数据
            comPlayerLandService.delete(comPlayerLand.getId());
            //todo 2.把删除的这个土地的数据记录到com_explain_land中去
            ComExplainLandVo comExplainLandVo = new ComExplainLandVo();
            comExplainLandVo = CopyUtil.copy(comPlayerLand, ComExplainLandVo.class);
            comExplainLandVo.setLandId(comPlayerLand.getConfigLandId());
            comExplainLandVo.setLandCreate(comPlayerLand.getCreateTime());
            comExplainLandVo.setExplainType(0);
            comExplainLandVo.setExplainDescribe("getState获取土地状态时候:土地租赁过期回收");
            comExplainLandVo.setCreateTime(new Date());
            comExplainLandVo.setUpdateTime(new Date());
            comExplainLandService.save(comExplainLandVo);
            //过期了返回一个状态
            return Result.of(null, false, ResultEnum.LAND_LEASE_EXPIRED.getMessage(), ResultEnum.LAND_LEASE_EXPIRED.getCode());
        }
        //土地时间
        //租赁的总时间 = 租赁时间 - 土地数据的创建时间
        Long leaseAllMill = comPlayerLandSimpleVo.getLeaseTime().getTime() - comPlayerLandSimpleVo.getCreateTime().getTime();
        Integer allDays = DateUtil.getDays(leaseAllMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseAllMill).intValue();
        comPlayerLandSimpleVo.setLeaseDays(allDays);
        Integer leaseDays = DateUtil.getDays(leaseDaysMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseDaysMill).intValue();
        comPlayerLandSimpleVo.setLeaseDaysRemaining(leaseDays);
        //返回一个租赁时间毫秒
        comPlayerLandSimpleVo.setLeaseDaysMill(leaseDaysMill);

        return Result.of(comPlayerLandSimpleVo);
    }


    /**
     * 种植土地，要先有土地才能种植
     *
     * @param userId
     * @return
     */
    @GetMapping("plant")
    @Transactional(rollbackFor = Exception.class)
    public Result<ComPlayerLandAndPlantVo> plantFunction(
            @RequestParam(value = "userId") String userId,
            @RequestParam(value = "landId") Integer landId,
            @RequestParam(value = "seedId") Integer seedId) {

        try {
            ComPlayerLand comPlayerLand = comPlayerLandService.findByUserIdAndLandId(userId, landId);
            //土地数据不存在
            if (comPlayerLand == null) {
                return Result.of(null, false, ResultEnum.LAND_DATA_ERROR.getMessage(), ResultEnum.LAND_DATA_ERROR.getCode());
            }
            if (!comPlayerLand.getIsLease().equals(1)) {
                return Result.of(null, false, ResultEnum.LAND_NOT_LEASE.getMessage(), ResultEnum.LAND_NOT_LEASE.getCode());
            }
            //土地已种植
            if (comPlayerLand.getIsPlant().equals(1)) {
                return Result.of(null, false, ResultEnum.LAND_IS_PLANT.getMessage(), ResultEnum.LAND_IS_PLANT.getCode());
            }
            //todo 用户没刷新时候，土地还存在。判定一下时间是否到期，到期不给收获
            //租赁的剩余天数 。
            Long leaseDaysMill = comPlayerLand.getLeaseTime().getTime() - DateUtil.getNowDate().getTime();
            if (leaseDaysMill <= 0) {
                //todo 清除记录的数据
                //    1.土地租赁到期，删除土地租赁数据
                comPlayerLandService.delete(comPlayerLand.getId());
                //todo 2.把删除的这个土地的数据记录到com_explain_land中去
                ComExplainLandVo comExplainLandVo = new ComExplainLandVo();
                comExplainLandVo = CopyUtil.copy(comPlayerLand, ComExplainLandVo.class);
                comExplainLandVo.setLandId(comPlayerLand.getConfigLandId());
                comExplainLandVo.setLandCreate(comPlayerLand.getCreateTime());
                comExplainLandVo.setExplainType(0);
                comExplainLandVo.setExplainDescribe("播种种子时:土地租赁过期回收");
                comExplainLandVo.setCreateTime(new Date());
                comExplainLandVo.setUpdateTime(new Date());
                comExplainLandService.save(comExplainLandVo);
                return Result.of(null, false, ResultEnum.LAND_LEASE_EXPIRED.getMessage(), ResultEnum.LAND_LEASE_EXPIRED.getCode());
            }


            ComMallSeedVo comMallSeedVo = comMallSeedService.findById(seedId);

            if (comMallSeedVo == null) {
                return Result.of(null, false, ResultEnum.SEED_DATA_ERROR.getMessage(), ResultEnum.SEED_DATA_ERROR.getCode());
            }
            //todo 背包种子减去 土地当前的倍数，需要多倍播种，即消耗多个种子
            ComPlayerGoods comPlayerGoodsSimpleVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 0);
            //先拿到一个 before
            Integer _beforeAmount = comPlayerGoodsSimpleVo.getAmount();
            //操作一个种子的倍数
            if (comPlayerGoodsSimpleVo.getAmount() < comPlayerLand.getLeaseMultiple()) {
                //如果背包种子数量不够土地操作倍数，比如土地5倍，种子应该消耗5个
                return Result.of(null, false, ResultEnum.PLAYER_GOODS_SEEDS_AMOUNT_ERROR.getMessage(), ResultEnum.PLAYER_GOODS_SEEDS_AMOUNT_ERROR.getCode());

            } else if (comPlayerGoodsSimpleVo.getAmount().equals(comPlayerLand.getLeaseMultiple())) {
                //数量一样清除背包数据
                comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
            } else {
                //_beforeAmount = comPlayerGoodsSimpleVo.getAmount();
                //否则减去土地倍数
                comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() - comPlayerLand.getLeaseMultiple());
                ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
                comPlayerGoodsService.save(comPlayerGoodsVo);
            }

            //todo 种植
            comPlayerLand.setIsPlant(1);
            //记录一个植物的种植id
            comPlayerLand.setPlantId(seedId);
            comPlayerLand.setPlantStart(new Date());
            //种植天数,成熟天数
            comPlayerLand.setPlantMature(comMallSeedVo.getMaturity());

            //生成一个标识,用来识别种植
            comPlayerLand.setPlantFlag(UUIDUtil.getUUID());

            //comPlayerLand.setLandDescribe();
            ComPlayerLandVo comPlayerLandVo = CopyUtil.copy(comPlayerLand, ComPlayerLandVo.class);
            comPlayerLandService.save(comPlayerLandVo);

            //todo 记录一个种植 操作信息
            ComPlayerLogVo _playerLogVo = new ComPlayerLogVo();
            _playerLogVo.setUserId(userId);
            _playerLogVo.setTId(comMallSeedVo.getId());
            _playerLogVo.setTName(comMallSeedVo.getName());
            _playerLogVo.setTType(1);//设置一个操作种子的id
            _playerLogVo.setTAmount(comPlayerLand.getLeaseMultiple());
            //交易后的数据
            _playerLogVo.setBeforeAmount(_beforeAmount);
            Integer _afterAmount = _beforeAmount - comPlayerLand.getLeaseMultiple();
            _afterAmount = _afterAmount < 0 ? 0 : _afterAmount;
            _playerLogVo.setAfterAmount(_afterAmount);
            _playerLogVo.setLMultiple(comPlayerLand.getLeaseMultiple());

            //收取时候信息记录
            _playerLogVo.setTPart(0d);
            _playerLogVo.setTLoss(0d); //损失的部分
            _playerLogVo.setBeforePart(0d);
            _playerLogVo.setAfterPart(0d);
            comPlayerLogService.save(_playerLogVo);

            ComPlayerLandAndPlantVo comPlayerLandAndPlantVo = CopyUtil.copy(comPlayerLand, ComPlayerLandAndPlantVo.class);
            comPlayerLandAndPlantVo.setSeedInfo(comMallSeedVo);

            //todo 返回一个计算的天数和小时，解决跨时区的问题
            //土地时间
            //租赁的总时间 = 租赁时间 - 土地数据的创建时间
            Long leaseAllMill = comPlayerLandAndPlantVo.getLeaseTime().getTime() - comPlayerLandAndPlantVo.getCreateTime().getTime();
            Integer allDays = DateUtil.getDays(leaseAllMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseAllMill).intValue();
            comPlayerLandAndPlantVo.setLeaseDays(allDays);
            //租赁的剩余天数
            Integer leaseDays = DateUtil.getDays(leaseDaysMill).intValue() <= 0 ? 0 : DateUtil.getDays(leaseDaysMill).intValue();
            comPlayerLandAndPlantVo.setLeaseDaysRemaining(leaseDays);

            //返回一个租赁时间毫秒
            comPlayerLandAndPlantVo.setLeaseDaysMill(leaseDaysMill);

            //种子时间
            //当前时间 > 种植时间+成熟期  = 说明可以收获了
            //获取当前时间 - 植物的成熟期 = 收获时间，收获时间 >= 种植时间，即可以收获
            Date _harvestTime = DateUtil.getNowDateMinusDay(comMallSeedVo.getMaturity());
            // 两个时间差, 逻辑是_harvestTime 时间慢慢接近种植时间
            long diff = comPlayerLandAndPlantVo.getPlantStart().getTime() - _harvestTime.getTime();
            //种植的剩余时间毫秒
            comPlayerLandAndPlantVo.setPlantDaysMill(diff);

            if (diff <= 0) {
                //说明可以收获了
                comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
            } else {
                comPlayerLandAndPlantVo.setPlantDaysRemaining(DateUtil.getDays(diff).intValue());
                comPlayerLandAndPlantVo.setPlantHoursRemaining(DateUtil.getHours(diff).intValue());
            }
            return Result.of(comPlayerLandAndPlantVo);

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 获取存在可偷取的用户列表
     *
     * @param userId
     * @return
     */
    @GetMapping("getCanStealUserList")
    public Result<List<ComPlayerLandAndUserInfoVo>> getCanStealUserList(
            @RequestParam(value = "userId") String userId,
            @RequestParam(value = "page", defaultValue = "0") Integer page,
            @RequestParam(value = "limit", defaultValue = "10") Integer limit
    ) {

        PageRequest pageable = PageRequest.of(page, limit, Sort.by(Sort.Direction.DESC, "plant_start"));

        List<ComPlayerLandAndUserInfoVo> comPlayerLands = comPlayerLandService.findAllByCanStealNotSelf(userId, pageable);

        return Result.of(comPlayerLands);
    }
}
