package com.sqx.modules.discSpinning.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sqx.common.annotation.Debounce;
import com.sqx.common.exception.CzgException;
import com.sqx.common.utils.*;
import com.sqx.modules.app.annotation.Login;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.discSpinning.entity.DiscSpinning;
import com.sqx.modules.discSpinning.entity.DiscSpinningRecord;
import com.sqx.modules.discSpinning.service.DiscSpinningRecordService;
import com.sqx.modules.discSpinning.service.DiscSpinningService;
import com.sqx.modules.orders.entity.Orders;
import com.sqx.modules.orders.service.OrdersService;
import com.sqx.modules.taskCenter.entity.TaskCenterRecord;
import com.sqx.modules.taskCenter.service.TaskCenterRecordService;
import com.sqx.modules.taskCenter.service.TaskCenterService;
import io.swagger.annotations.*;
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 springfox.documentation.annotations.ApiIgnore;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@Api(value = "大转盘", tags = {"大转盘"})
@RequestMapping
public class DiscSpinningController {

    private final DiscSpinningService discSpinningService;
    private final DiscSpinningRecordService recordService;
    private final CommonInfoService commonRepository;
    private final OrdersService ordersService;
    private final TaskCenterService taskCenterService;
    private final TaskCenterRecordService taskRecordService;
    private final UserService userService;
    private final RedisUtils redisUtils;
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);

    @Autowired
    public DiscSpinningController(CommonInfoService commonRepository, DiscSpinningService discSpinningService,
                                  OrdersService ordersService, DiscSpinningRecordService recordService,
                                  TaskCenterService taskCenterService, UserService userService, RedisUtils redisUtils,
                                  TaskCenterRecordService taskRecordService) {
        this.commonRepository = commonRepository;
        this.discSpinningService = discSpinningService;
        this.ordersService = ordersService;
        this.recordService = recordService;
        this.taskCenterService = taskCenterService;
        this.userService = userService;
        this.redisUtils = redisUtils;
        this.taskRecordService = taskRecordService;
    }

    @PostMapping("/discSpinning/insertDiscSpinning")
    @ApiOperation("添加大转盘")
    @Transactional
    public Result insertDiscSpinning(@RequestBody DiscSpinning discSpinning) {
        discSpinning.setCreateTime(DateUtils.format(new Date()));
        discSpinning.setNumber(discSpinning.getOdds());
        discSpinningService.save(discSpinning);

        List<DiscSpinning> prizes = discSpinningService.list(new QueryWrapper<DiscSpinning>().eq("disc_type", discSpinning.getDiscType()).orderByAsc("type", "id"));
        BigDecimal number = BigDecimal.ZERO;
        for (DiscSpinning prize : prizes) {
            number = number.add(prize.getOdds());
            prize.setNumber(number);
        }
        BigDecimal totalOdds = prizes.stream()
                .map(DiscSpinning::getOdds)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        if (totalOdds.compareTo(new BigDecimal(100)) > 0) {
            return Result.error("中奖概率总和 不可超过100");
        }
        discSpinningService.updateBatchById(prizes);
        return Result.success();
    }

    @GetMapping("/discSpinning/{id}")
    @ApiOperation("通过Id查询详情")
    public Result selectOne(@PathVariable Integer id) {
        return Result.success().put("data", discSpinningService.getById(id));
    }

    @PostMapping("/discSpinning/updateDiscSpinning")
    @ApiOperation("修改大转盘")
    public Result updateDiscSpinning(@RequestBody DiscSpinning discSpinning) {
        discSpinningService.updateById(discSpinning);

        List<DiscSpinning> prizes = discSpinningService.list(new QueryWrapper<DiscSpinning>().eq("disc_type", discSpinning.getDiscType()).orderByAsc("type", "id"));
        BigDecimal number = BigDecimal.ZERO;
        for (DiscSpinning prize : prizes) {
            number = number.add(prize.getOdds());
            prize.setNumber(number);
        }
        BigDecimal totalOdds = prizes.stream()
                .map(DiscSpinning::getOdds)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        if (totalOdds.compareTo(new BigDecimal(100)) > 0) {
            return Result.error("中奖概率总和 不可超过100");
        }
        discSpinningService.updateBatchById(prizes);
        return Result.success();
    }

    @PostMapping("/discSpinning/deleteDiscSpinning")
    @ApiOperation("删除大转盘")
    public Result deleteDiscSpinning(Long id) {
        discSpinningService.removeById(id);
        return Result.success();
    }

    @GetMapping("/app/discSpinning/selectDiscSpinning")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "source", value = "1 普通转盘 2 周任务转盘 3 月任务转盘", dataTypeClass = Integer.class),
    })
    @ApiOperation("查询大转盘")
    public Result selectDiscSpinning(@RequestParam(required = false, defaultValue = "1") Integer source) {
        PageHelper.startPage(1,20);
        return Result.success().put("data", PageUtils.page(new PageInfo<>(discSpinningService.list(
                new QueryWrapper<DiscSpinning>().eq("disc_type", source).orderByAsc("disc_type", "odds"))),true)
        );
    }


    @Login
    @GetMapping("/app/discSpinning/drawCount")
    @ApiOperation("获取大转盘抽奖次数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "source", value = "`1` 订单拉起抽奖 `2` 周任务拉起抽奖 `3` 月任务拉起抽奖", dataTypeClass = Integer.class),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "{\"sum\":\"总抽奖次数\",\"count\":\"剩余抽奖次数\"}"),
    })
    public Result drawCount(@ApiIgnore @RequestAttribute("userId") Long userId, @RequestParam(required = false, defaultValue = "1") Integer source) {
        Map<String, Object> map = new HashMap<>();
        int drawCount = Integer.parseInt(commonRepository.findOne(901).getValue());
        map.put("sum", drawCount);
        if (source != null && !source.equals(1)) {
            //任务可抽奖次数
            map.put("count", taskCenterService.countTaskDisc(userId, source.toString()));
        } else {
            //订单可抽奖次数
            int i = recordService.countDraw(userId);
            if (drawCount - i > 0) {
                map.put("count", ordersService.selectOrdersCountStatisticsByDay(userId, drawCount - i));
            } else {
                map.put("count", 0);
            }
        }
        return Result.success(map);
    }

    @Login
    @GetMapping("/app/discSpinning/draw")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "source", value = "1 普通转盘 2 周任务转盘 3 月任务转盘", dataTypeClass = Integer.class),
    })
    @ApiOperation("抽取大转盘")
    @Debounce(interval = 3000, value = "#userId")
    public Result draw(@ApiIgnore @RequestAttribute("userId") Long userId, @RequestParam(required = false, defaultValue = "1") Integer source) throws CzgException {
        double amount = 0;
        Long sourceId = null;
        Integer i = recordService.countDraw(userId);
        if (source == null || source.equals(1)) {
            source = 1;
            //订单抽奖
            int drawCount = Integer.parseInt(commonRepository.findOne(901).getValue());
            if (i != null && i >= drawCount) {
                throw new CzgException("当日可抽奖次数已超限");
            }
            Orders orders = ordersService.selectOrdersByDay(userId);
            if (orders == null) {
                throw new CzgException("无可抽奖机会");
            }
            amount = orders.getPayMoney().doubleValue();
            sourceId = orders.getOrdersId();
        } else {
            String redisKey = "";
            if (source.equals(2)) {
                redisKey = RedisKeys.getDateKey("spinning:amount:taskW") + userId;
            } else if (source.equals(3)) {
                redisKey = RedisKeys.getDateKey("spinning:amount:taskM") + userId;
            }
            Map<String, Object> week = redisUtils.get(redisKey, Map.class);
            for (Map.Entry<String, Object> entry : week.entrySet()) {
                int value = new BigDecimal(entry.getValue().toString()).intValue();
                if (value > 1) {
                    value = value - 1;
                    week.put(entry.getKey(), value);
                    sourceId = Long.valueOf(entry.getKey());
                    break;
                } else {
                    TaskCenterRecord centerRecord = new TaskCenterRecord();
                    centerRecord.setUserId(userId);
                    centerRecord.setTaskId(Long.valueOf(entry.getKey()));
                    if (source.equals(2)) {
                        sourceId = Long.valueOf(entry.getKey());
                        centerRecord.setSourceId(Long.getLong(entry.getKey()));
                    }
                    centerRecord.setName(source.equals(2) ? "周任务奖励" : "月任务奖励");
                    centerRecord.setType(9);
                    centerRecord.setNumber(1);
                    centerRecord.setCreateTime(DateUtil.now());
                    centerRecord.setUpdateTime(DateUtil.now());
                    taskRecordService.save(centerRecord);
                    week.remove(entry.getKey());
                    break;
                }
            }
            redisUtils.set(redisKey, week, DateUtils.todayAfterSecond());
        }
        if (source == 1 && sourceId == null) {
            throw new CzgException("异常请求");
        }
        if (DataLimitUtil.isAllowed(RedisKeys.getDateKey("spinning:draw:") + sourceId, 120)) {
            DiscSpinningRecord draws = discSpinningService.draws(i == null ? 1 : i + 1, amount, sourceId, userId, source);
            executor.schedule(() -> discSpinningService.receive1(draws), 4, TimeUnit.SECONDS);
            return new Result().put("data", draws);
        } else {
            throw new CzgException("异常请求");
        }
    }

    @ApiOperation("大转盘奖项领取")
    @Debounce(interval = 5000, value = "#receive.id")
    @PostMapping("/app/discSpinning/receive")
    public Result receive(@RequestBody DiscSpinningRecord receive) {
        return Result.success().put("data", 1);
    }


}

