package com.tzy.controller.prize;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.tzy.annotation.ApiLimitRule;
import com.tzy.annotation.ApiLog;
import com.tzy.annotation.RequireRoles;
import com.tzy.app.domain.act.AmountActResult;
import com.tzy.app.domain.act.ShareActResult;
import com.tzy.app.dto.order.OrderSubmitDTO;
import com.tzy.app.dto.order.PrizeOrderParam;
import com.tzy.common.annotation.SensitiveData;
import com.tzy.common.config.handle.ApiVersion;
import com.tzy.common.constant.Constants;
import com.tzy.common.constant.MsgConstants;
import com.tzy.common.constant.NoticeMsgModel;
import com.tzy.common.core.domain.entity.SysDictData;
import com.tzy.common.dto.*;
import com.tzy.common.dto.act.*;
import com.tzy.common.dto.group.ActReportDTO;
import com.tzy.common.enums.BusinessType;
import com.tzy.common.exception.AppAssert;
import com.tzy.common.exception.ServiceException;
import com.tzy.common.utils.*;
import com.tzy.common.utils.bean.DozerUtils;
import com.tzy.common.utils.bean.JSONTools;
import com.tzy.common.utils.http.forest.SaasForestClient;
import com.tzy.common.utils.http.forest.param.DrawOrderDTO;
import com.tzy.common.utils.http.forest.param.PayReqParam;
import com.tzy.common.utils.http.forest.param.ResultDTO;
import com.tzy.coupon.card.service.ITzyCardBaseInfoService;
import com.tzy.dto.SimplePrizeRecord;
import com.tzy.dto.local.card.CardQuery;
import com.tzy.framework.util.RedisUtils;
import com.tzy.framework.web.domain.LimitRule;
import com.tzy.service.MallOrderService;
import com.tzy.sportcard.api.bean.act.*;
import com.tzy.sportcard.api.bean.param.PointDetailParam;
import com.tzy.sportcard.api.domain.AppUserInfoDto;
import com.tzy.sportcard.api.domain.GroupInfo;
import com.tzy.sportcard.api.dto.prize.AppActManageDTO;
import com.tzy.sportcard.api.dto.prize.AppActPrizeDTO;
import com.tzy.sportcard.api.dto.prize.PublicPrizeCodeDTO;
import com.tzy.sportcard.api.dto.prize.UserActPointDTO;
import com.tzy.sportcard.api.service.AsyncAppService;
import com.tzy.sportcard.api.service.GroupApiService;
import com.tzy.sportcard.api.service.MineApiService;
import com.tzy.sportcard.base.service.CommonCacheService;
import com.tzy.sportcard.group.domain.CardGroupOrderInfo;
import com.tzy.sportcard.group.service.AppActService;
import com.tzy.sportcard.group.service.ICardGroupOrderInfoService;
import com.tzy.sportcard.group.service.impl.AppActServiceImpl;
import com.tzy.sportcard.point.domain.AppUserPointRecord;
import com.tzy.system.domain.TzyShippingAddress;
import com.tzy.system.service.ITzyShippingAddressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.teasoft.bee.osql.*;
import org.teasoft.bee.osql.annotation.Ignore;
import org.teasoft.honey.osql.core.ConditionImpl;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author by po'yi
 * @Classname AppActController
 * @Description
 * @Date 2022/8/3 13:24
 */
@Api(value = "app活动相关")
@RestController
@RequestMapping("/api/{version}/act")
@Slf4j
@CrossOrigin(allowCredentials = "true")
public class AppActController {
    @Autowired
    private MineApiService mineApiService;
    @Autowired
    private SuidRich suidRich;
    @Autowired
    private AppActService appActService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private ICardGroupOrderInfoService cardGroupOrderInfoService;
    @Autowired
    private AsyncAppService asyncAppService;
    @Autowired
    private GroupApiService groupApiService;
    @Resource
    private CommonCacheService commonCacheService;
    @Autowired
    private MallOrderService mallOrderService;
    @Resource
    private SaasForestClient saasForestClient;
    @Autowired
    private ITzyShippingAddressService shippingAddressService;
    @Resource
    private ITzyCardBaseInfoService cardBaseInfoService;
    @Value("${saasService.baseurl:http://poyee-api-saas}")
    private String saasBaseUrl;
    @Value("${saasService.userPrizeUrl:/api/v1/act/user/prize}")
    private String userPrizeUrl;
    @Value("${saasService.actDetailUrl:/api/v1/act/draw/detail}")
    private String actDetailUrl;
    @Value("${saasService.actPrizelUrl:/api/v1/act/draw/prize}")
    private String actPrizeUrl;
    @Value("${saasService.drawSubmitUrl:/api/v1/act/draw/submit}")
    private String drawSubmitUrl;
    @Value("${saasService.drawOrderListUrl:/api/v1/order/list}")
    private String drawOrderListUrl;
    @Value("${saasService.drawOrderDetailUrl:/api/v1/order/detail}")
    private String drawOrderDetailUrl;
    @Value("${saasService.drawPrizeSubmitUrl:/api/v1/order/prize/submit}")
    private String drawPrizeSubmitUrl;
    @Value("${saasService.drawOrderPrepayUrl:/api/v1/order/prepay}")
    private String drawOrderPrepayUrl;
    @Value("${saasService.drawPayCatUrl:/api/v1/order/payment/cat}")
    private String drawPayCatUrl;
    @Value("${saasService.localOrderDrawUrl:/local/order/draw}")
    private String localOrderDrawUrl;
    @Value("${saasService.drawSelectedUrl:/api/v1/act/draw/selected}")
    private String drawSelectedUrl;
    @Value("${saasService.editActOrderAddr:/api/v1/order/edit/address}")
    private String editActOrderAddr;
    @Value("${saasService.delActOrderUrl:/api/v1/order/del}")
    private String delActOrderUrl;
    @Value("${saasService.confirmActOrderUrl:/api/v1/order/express/confirm}")
    private String confirmActOrderUrl;

    private static final String GROUP_GIFT_618="group_gift_618";

    @ApiLog(title = "获取活动类型", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取活动类型")
    public OutDTO getPrize(@RequestBody InDto inDto) {
        AppActManageDTO actManage = new AppActManageDTO();
        actManage.setType(inDto.getString("type"));
        actManage.setStatus(1);
        List<AppActManageDTO> actList = suidRich.select(actManage);
        return OutDTO.ok().put("actList", actList);
    }

    @ApiLog(title = "获取活动详情", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/simpleInfo", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取活动详情")
    public OutDTO getSimpleActInfo(@RequestBody InDto inDto) {
        return OutDTO.ok().put("actInfo", getActInfoById(inDto.get("actId")));
    }


    private AppActManageDTO getActInfoById(Object actIdObj) {
        Integer actId = (Integer) actIdObj;
        if (actId == null) {
            throw new ServiceException(500, "活动参数未传!");
        }
        AppActManageDTO actManage = new AppActManageDTO();
        actManage.setId(actId.longValue());
        actManage.setStatus(1);
        actManage = suidRich.selectOne(actManage);
        if (actManage == null) {
            throw new ServiceException(500, "活动不存在!");
        }
        actManage.setPrizeList(getPrizes(actId));
        return actManage;
    }

    @ApiLog(title = "获取活动详情", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/info", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取活动详情")
    public OutDTO getActInfo(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        AppActManageDTO actManage = getActInfoById(inDto.get("actId"));
        actManage.setUserTimes(appActService.getUserActTimes(userInfo.getId(), actManage));
        PayActDTO payAct = getPayAct();
        Map<String, BigDecimal> actAmountData = ImmutableMap.of("frozen_amount", BigDecimal.ZERO, "consume_amount", BigDecimal.ZERO);
        long userActPoint=0L;
        if (payAct != null) {
            actAmountData = cardGroupOrderInfoService.getActGroupAmount(DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, payAct.getStartTime()),
                    DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, payAct.getEndTime()), userInfo.getId(), null);
        } else if (StringUtils.isNotEmpty(actManage.getPointType()) && !Constants.POINT_TYPE_COMMON.equals(actManage.getPointType())) {
            userActPoint = appActService.getUserPointByType(userInfo.getId(), actManage.getPointType());
            actAmountData = cardGroupOrderInfoService.getActGroupAmount(actManage.getStartTime(), actManage.getEndTime(), userInfo.getId(), actManage.getPointType());
        }
        int drawNum = actManage.getUserTimes();
        if (actManage.getDayLimitNum() > 0) {
            drawNum = getUserDrawCount(actManage, drawNum);
            drawNum = Math.max(0, drawNum);
        }
        actManage.setRuleConfig(null);
        return OutDTO.ok().put("actInfo", actManage).put("actAmount", actAmountData).put("drawNum",drawNum).put("userActPoint",userActPoint);
    }

    @ApiLog(title = "获取活动积分", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/points", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取活动积分")
    public OutDTO getActCommonInfo(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        if(inDto == null || inDto.get("actType") == null){
            return OutDTO.error500("参数为空");
        }
        String actType = inDto.getString("actType");
        List<SysDictData> sysDictDatas = commonCacheService.getCommonDictData("app_hot_type_times_cache",
                actType,"1", null, -1);
        Map<String, BigDecimal> actAmountData = Maps.newHashMap();
        if(!CollectionUtils.isEmpty(sysDictDatas)) {
            JSONObject jsonObject = JSONTools.parseObject(sysDictDatas.get(0).getDictValue());
            /*boolean hasType = jsonObject.getBoolean("hasType"); // 是否传积分类型查拼团
            String pointType = null;G
            if(hasType){
                pointType = jsonObject.getString("pointType");
            }*/
            BigDecimal frozenAmount = cardGroupOrderInfoService.getActFrozenAmountV2(
                    jsonObject.getDate("startTime"),
                    jsonObject.getDate("endTime"),
                    userInfo.getId()
            );
            BigDecimal rate = jsonObject.getBigDecimal("rate");
            if(frozenAmount.compareTo(BigDecimal.ZERO) > 0){
                frozenAmount = frozenAmount.divide(rate,0, RoundingMode.DOWN);
            }
            BigDecimal consumeAmount = cardGroupOrderInfoService.getActConsumeAmountV2(userInfo.getId(), jsonObject.getString("pointType"));
            if(consumeAmount.compareTo(BigDecimal.ZERO) > 0){
                consumeAmount = consumeAmount.divide(rate.multiply(new BigDecimal("100")),0, RoundingMode.DOWN);
            }
            actAmountData.put("frozen_amount", frozenAmount);
            actAmountData.put("consume_amount", consumeAmount);
        }
        return OutDTO.ok().put("actAmount", actAmountData);
    }

    private int getUserDrawCount(AppActManageDTO actManage, int drawNum) {
        if (StringUtils.isNotEmpty(actManage.getRuleConfig())) {
            //小时范围内限购
            DrawRuleConfig ruleConfig = JSON.parseObject(actManage.getRuleConfig(), DrawRuleConfig.class);
            List<LimitConfigDTO> limitConfigs = ruleConfig.getLimitConfig();
            if (!CollectionUtils.isEmpty(limitConfigs)) {
                int curHour = DateUtils.getCurrentHour();
                LimitConfigDTO limitConfig = limitConfigs.stream().filter(l -> curHour < l.getEndHour() && curHour >= l.getStartHour())
                        .findFirst().orElse(null);
                if (limitConfig != null) {
                    int limitHourNum = limitConfig.getLimitNum() == null ? 0 : limitConfig.getLimitNum();
                    int actHourCount = appActService.getActCount(actManage.getId().intValue(), false, limitConfig.getStartHour(), limitConfig.getEndHour());
                    drawNum = limitHourNum - actHourCount;
                }
            }
        } else {
            int actDayCount = appActService.getActCount(actManage.getId().intValue(), true);
            drawNum = actManage.getDayLimitNum() - actDayCount;
        }
        return drawNum;
    }


    private PayActDTO getPayAct() {
        Object cache = redisUtils.get("pay_act_cache_turntable");
        if (cache != null) {
            return (PayActDTO) cache;
        }
        List<SysDictData> payActTypes = asyncAppService.getPayActs(PayActDTO.TYPE_PAY_AMOUNT_TURNTABLE);
        if (CollectionUtils.isEmpty(payActTypes)) {
            return null;
        }
        SysDictData actData = payActTypes.get(0);
        PayActDTO payAct = JSONTools.jsonStr2obj(actData.getDictValue(), PayActDTO.class);
        redisUtils.set("pay_act_cache_turntable_info", payAct, 600);
        return payAct;
    }


    private List<AppActPrizeDTO> getPrizes(Integer actId) {
        Object actCache = redisUtils.get(Constants.ACT_PRIZE_INFO_CACHE + actId);
        List<AppActPrizeDTO> prizeList;
        if (actCache == null) {
            AppActPrizeDTO actPrizeDTO = new AppActPrizeDTO();
            actPrizeDTO.setActId(actId.longValue());
            actPrizeDTO.setStatus(1);
            prizeList = suidRich.selectOrderBy(actPrizeDTO, "sortQuery", new OrderType[]{OrderType.DESC});
            if (prizeList.isEmpty()) {
                throw new ServiceException(500, "奖品信息异常,请联系管理员!");
            }
            redisUtils.set(Constants.ACT_PRIZE_INFO_CACHE + actId, prizeList);
        } else {
            prizeList = (List<AppActPrizeDTO>) actCache;
        }
        return prizeList;
    }


    @ApiLog(title = "获取用户参与活动记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/getUserActRecord", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取用户参与活动记录")
    public OutDTO getUserActRecord(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }

        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        AppActPrizeRecord recordCondition = new AppActPrizeRecord();
        recordCondition.setUserId(userInfo.getId());
        recordCondition.setActId(actId.longValue());

        Condition condition = new ConditionImpl();
        condition.orderBy("id", OrderType.DESC);
        condition.start((inDto.getPageNo() - 1) * inDto.getPageSize()).size(inDto.getPageSize());

        List<AppActPrizeRecord> recordList = suidRich.select(recordCondition, condition);
        return OutDTO.ok().put("recordList", recordList);
    }


    @ApiLog(title = "获取活动记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/getActRecord", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取活动记录")
    public OutDTO getActRecord(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }

        AppActPrizeRecord recordCondition = new AppActPrizeRecord();
        recordCondition.setActId(actId.longValue());
        recordCondition.setShowStatus(1);

        Condition condition = new ConditionImpl();
        condition.orderBy("id", OrderType.DESC);
        condition.start(0).size(10);

        List<AppActPrizeRecord> recordList = suidRich.select(recordCondition, condition);
        List<SimplePrizeRecord> records = recordList.stream()
                .map(r -> new SimplePrizeRecord(r.getPrizeName(), r.getNickname().substring(0, 1) + "***", r.getAvatar())).collect(Collectors.toList());
        return OutDTO.ok().put("recordList", records);
    }


    @ApiLog(title = "大转盘抽奖", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luckDraw", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("大转盘抽奖")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER,lockCount = 3,lockTime = 120,msg = "操作频繁,请稍后再试!")
    public OutDTO luckDraw(@RequestBody InDto inDto) {
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        checkIsInfoAct(actId, null);
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        AppActPrizeDTO userPrize = appActService.drawPrize(actId, userInfo, null);
        OutDTO ok = OutDTO.ok();
        if (Constants.SKU_ACT_TYPE_COUPON.equals(userPrize.getType())) {
            ok.put("prizeInfo", cardBaseInfoService.getPrizeInfo(userPrize.getPrizeId()));
        }
        return ok.put("userPrize", userPrize);
    }

    @ApiLog(title = "大转盘抽奖(拼团拼团关联)", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/info/luckDraw", method = RequestMethod.POST)
    @ApiVersion(2.0)
    @ApiOperation("大转盘抽奖(拼团关联)")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER,lockCount = 3,lockTime = 120,msg = "操作频繁,请稍后再试!")
    public OutDTO infoLuckDraw(@RequestBody InDto inDto) {
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        Integer refId = inDto.getIntegerParam("refId");
        checkIsInfoAct(actId,refId);
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        AppActPrizeDTO userPrize = appActService.drawPrize(actId, userInfo, refId);
        OutDTO ok = OutDTO.ok();
        if (Constants.SKU_ACT_TYPE_COUPON.equals(userPrize.getType())) {
            ok.put("prizeInfo", cardBaseInfoService.getPrizeInfo(userPrize.getPrizeId()));
        }
        return ok.put("userPrize", userPrize);
    }

    private void checkIsInfoAct(Integer actId, Integer refId) {
        List<SysDictData> typeData = commonCacheService.getCommonDictData(Constants.INFO_GIVE_DRAW, null, "1", Constants.INFO_GIVE_DRAW, 84600);
        if (CollectionUtils.isEmpty(typeData)) {
            return;
        }
        SysDictData data = typeData.get(0);
        long refActId = data.getDictSort();
        if (refActId != actId.longValue()) {
            return;
        }
        if (refId == null) {
            throw new ServiceException("活动参数未传!");
        }
        GroupInfo info = groupApiService.getGroupInfoById(refId);
        AppAssert.notNull(info, "拼团不存在!");
        if (info.getStatus() < 203 || info.getStatus() == 999) {
            throw new ServiceException("拼团状态不符合要求!");
        }
        if (!GROUP_GIFT_618.equals(data.getDictValue()) && !Integer.valueOf(data.getDictValue()).equals(info.getPaniniListId())) {
            throw new ServiceException("拼团未参与活动");
        }
    }

    @ApiLog(title = "获取竞猜活动详情", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/guess/info", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取竞猜活动详情")
    public OutDTO getGuessActInfo(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        GuessActDTO actInfo = getGuessAct(actId);
        List<GuessTeamDTO> guessTeams = appActService.selectGuessTeam(actInfo.getId(), userInfo.getId(), true);
        actInfo.setGuessTeams(guessTeams);
        AppActGuessTeam team = new AppActGuessTeam();
        team.setActId(actId.longValue());
        ConditionImpl condition = new ConditionImpl();
        condition.and().op("guessResult", Op.gt, 0);
        String count = suidRich.selectWithFun(team, FunctionType.COUNT, "*", condition);

        return OutDTO.ok().put("actInfo", actInfo).put("hasRank", Integer.valueOf(count) > 0)
                .put("hasRecord", appActService.getUserIsGuess(userInfo.getId(), actId))
                .put("turntableNums", appActService.getUserActTurntableNums(userInfo.getId(), actId));
    }

    private GuessActDTO getGuessAct(Integer actId) {
        AppActManageDTO actManage = new AppActManageDTO();
        actManage.setId(actId.longValue());
        actManage.setStatus(1);
        actManage = suidRich.selectOne(actManage);
        if (actManage == null) {
            throw new ServiceException(500, "活动不存在!");
        }

        GuessActDTO actInfo = DozerUtils.map(actManage, GuessActDTO.class);
        return actInfo;
    }

    @ApiLog(title = "获取竞猜日程", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/guess/team/list", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取竞猜日程")
    public OutDTO getGuessActTeams(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        List<GuessTeamDTO> guessTeams = appActService.selectGuessTeam(actId.longValue(), userInfo.getId(), false);
        Map<String, List<GuessTeamDTO>> collect = guessTeams.stream().collect(Collectors.groupingBy(g -> DateUtils.dateTime(g.getMatchStartTime())));
        return OutDTO.ok().put("guessTeams", new TreeMap<>(collect));
    }

    @ApiLog(title = "用户竞猜历史", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/guess/user/record", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("用户竞猜历史")
    public OutDTO getUserGuessRecord(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("参数为空");
        }
        Integer guessStatus = (Integer) inDto.get("status");
        GuessUserDTO userRank = appActService.getUserActRanking(actId, userInfo.getId()).getCurrentUser();
        AppActGuessRecord param = new AppActGuessRecord();
        param.setActId(actId.longValue());
        param.setUserId(userInfo.getId().longValue());
        String count = suidRich.selectWithFun(param, FunctionType.COUNT, "*");
        userRank.setGuessTotalNums(Integer.valueOf(count));
        List<GuessHistoryRecord> records = appActService.getUserGuessHistoryRecord(userInfo.getId(), actId, guessStatus);
        return OutDTO.ok().put("userRank", userRank).put("records", records);
    }

    @ApiLog(title = "用户竞猜", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/guess/user/choice", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("用户竞猜")
    public OutDTO userGuessTeam(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        Integer teamId = (Integer) inDto.get("teamId");
        Integer userGuessResult = (Integer) inDto.get("userGuessResult");
        if (teamId == null || userGuessResult == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActGuessRecord param = new AppActGuessRecord();
        param.setUserId(userInfo.getId().longValue());
        param.setNickname(userInfo.getNickname());
        param.setAvatar(userInfo.getAvatar());
        param.setActTeamId(teamId.longValue());
        param.setUserGuessResult(userGuessResult);
        appActService.userGuessTeam(param);
        return OutDTO.ok();
    }

    @ApiLog(title = "参与用户竞猜数据", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/guess/team/user/nums", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("参与用户竞猜数据")
    public OutDTO getTeamGuessNums(@RequestBody InDto inDto) {
        Integer teamId = (Integer) inDto.get("teamId");
        if (teamId == null) {
            return OutDTO.error500("参数为空!");
        }
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        AppActGuessTeam team = new AppActGuessTeam();
        team.setId(teamId.longValue());
        team = suidRich.selectOne(team);
        GuessTeamDTO teamDTO = DozerUtils.map(team, GuessTeamDTO.class);
        AppActGuessRecord param = new AppActGuessRecord();
        param.setUserId(userInfo.getId().longValue());
        param.setActTeamId(teamId.longValue());
        List<AppActGuessRecord> records = appActService.getUserGuessRecord(param);
        int userChoice = 0;
        if (!records.isEmpty()) {
            userChoice = records.get(0).getUserGuessResult();
        }
        List<TeamResultDTO> resultList = appActService.getTeamGuessNums(teamId);
        Map<Integer, List<TeamResultDTO>> collect = resultList.stream().collect(Collectors.groupingBy(TeamResultDTO::getGuessResult));
        List<TeamResultDTO> winData = collect.get(3);
        List<TeamResultDTO> eqData = collect.get(2);
        List<TeamResultDTO> loseData = collect.get(1);
        int winCount = winData == null ? 0 : winData.get(0).getNums();
        int eqCount = eqData == null ? 0 : eqData.get(0).getNums();
        int loseCount = loseData == null ? 0 : loseData.get(0).getNums();
        int total = winCount + eqCount + loseCount;
        int winRate = 0;
        int loseRate = 0;
        int eqRate = 0;
        if (total > 0) {
            winRate = winCount == 0 ? 0 : (int) winCount * 100 / total;
            loseRate = loseCount == 0 ? 0 : (int) loseCount * 100 / total;
            eqRate = eqCount == 0 ? 0 : (int) eqCount * 100 / total;
            int totalRate = eqRate + winRate + loseRate;
            if (totalRate < 100) {
                winRate += 100 - totalRate;
            } else if (totalRate > 100) {
                loseRate -= totalRate - 100;
            }
        }

        return OutDTO.ok().put("team", teamDTO)
                .put("userChoice", userChoice).put("total", total)
                .put("winRate", winRate).put("winCount", winCount)
                .put("loseRate", loseRate).put("loseCount", loseCount)
                .put("eqRate", eqRate).put("eqCount", eqCount);
    }

    @ApiLog(title = "竞猜排行榜", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/guess/rank/list", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("竞猜排行榜")
    public OutDTO getActRankList(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("参数为空");
        }
        return OutDTO.ok().put("rankList", appActService.getUserActRanking(actId, userInfo.getId()));
    }


    @ApiLog(title = "获取用户抽奖记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/getUserTurntableRecord", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取用户抽奖记录")
    public OutDTO getUserTurntableRecord(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        List<AppActPrizeRecord> recordList = appActService.getUserTurntableRecord(actId, inDto.getUserId());
        return OutDTO.ok().put("recordList", recordList);
    }

    @ApiLog(title = "获取瓜分奖励的人数", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/getPrizeQualifys", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("获取瓜分奖励的人数")
    public OutDTO getPrizeQualifys(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        return OutDTO.ok().put("prizeQualifys", appActService.getPrizeQualifys(actId));
    }


    @ApiLog(title = "鸿运值兑换", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("鸿运值兑换")
    @ApiLimitRule(seconds = 5, limitCount = 25, type = LimitRule.ACT, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchange(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        Integer purchaseCount = (Integer) inDto.get("purchaseCount");
        if (purchaseCount == null || purchaseCount < 1) {
            return OutDTO.error500("兑换数量异常!");
        }
        Boolean anonymous = (Boolean) inDto.get("anonymous");
        int isShow = anonymous != null && anonymous ? 0 : 1;
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        appActService.luckPointExchange(actId, purchaseCount, userInfo, isShow,true);
        return OutDTO.ok();
    }


    @ApiLog(title = "重新申请抽奖码", businessType = BusinessType.SEARCH)
    @ResponseBody
    //@RequestMapping(value = "/luck/code/repeat", method = RequestMethod.POST)
    //@ApiVersion(1.0)
    @ApiOperation("重新申请抽奖码")
    public OutDTO repeat(@RequestBody InDto inDto) {
        Integer prizeRecordId = (Integer) inDto.get("prizeRecordId");
        if (prizeRecordId == null) {
            return OutDTO.error500("参数未传!");
        }
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        appActService.checkLuckyCode(prizeRecordId, userInfo.getId());
        return OutDTO.ok();
    }


    /**
     * 获取用户活动积分明细
     */
    @ApiLog(title = "获取用户活动积分明细", businessType = BusinessType.SEARCH, indto = "{{inDto}}")
    @ApiOperation("获取用户活动积分明细")
    @ResponseBody
    @RequestMapping(value = "/user/point/type", method = RequestMethod.POST)
    public OutDTO getUserActPointByType(@RequestBody InDto inDto) {
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        PointDetailParam detailParam = inDto.buildParam(new PointDetailParam());
        detailParam.setPageNo(inDto.getPageNo());
        detailParam.setPageSize(inDto.getPageSize());
        detailParam.setUserId(userInfo.getId());
        UserActPointDTO userActPointDTO = appActService.getUserActPointByType(detailParam);
        return OutDTO.ok().put("userActPoint", userActPointDTO);
    }


    @ApiLog(title = "新手指引记录", businessType = BusinessType.SEARCH, indto = "{{inDto}}")
    @ApiOperation("新手指引记录")
    @ResponseBody
    @PostMapping(value = "/user/show")
    public OutDTO getUserShow(@RequestBody InDto inDto) {
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        String type = inDto.getString("type");
        if (StringUtils.isEmpty(type)) {
            return OutDTO.error500(MsgConstants.PARAM_EMPTY);
        }
        if (Constants.ENFORCE_FACE_VERIFY_REMIND.equals(type)) {
            String key = "user_show_" + type + user.getId();
            if (redisUtils.hasKey(key)) {
                return OutDTO.ok().put("status", 1);
            } else {
                redisUtils.set(key, 1, 600);
                return OutDTO.ok().put("status", 0);
            }
        }
        String key = "user_show_" + type;
        if (redisUtils.hHasKey(key, user.getId().toString())) {
            return OutDTO.ok().put("status", 1);
        }
        redisUtils.hset(key, user.getId().toString(), 1);
        return OutDTO.ok().put("status", 0);
    }

    @ApiLog(title = "获取指定checklist收集信息", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/checklist")
    //@ApiVersion(1.0)
    @ApiOperation("获取指定checklist活动")
    public OutDTO selectUserCollectListAct(@RequestBody InDto inDto) {
        Integer paniniBaseId = (Integer) inDto.get("paniniBaseId");
        if (paniniBaseId == null) {
            return OutDTO.error500("参数【paniniBaseId】为空!");
        }
        String actType = inDto.getString("actType");
        if (StringUtils.isEmpty(actType)) {
            return OutDTO.error500("参数【actType】为空!");
        }
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("参数【actId】为空!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        UserListActDTO userList = appActService.buildUserListActData(user.getId(), paniniBaseId, actType, actId);
        if (actType.endsWith(Constants.ACT_GOODS_TYPE_PLAYER) && !CollectionUtils.isEmpty(userList.getTeamPlayerList())) {
            addPlayerData(paniniBaseId, userList.getTeamPlayerList());
        }
        return OutDTO.ok().put("userList", userList);
    }

    @ApiLog(title = "获取checklist活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/collect/id")
    @ApiOperation("获取指定checklist活动")
    public OutDTO selectListAct(@RequestBody InDto inDto) {
        Integer paniniBaseId = (Integer) inDto.get("paniniBaseId");
        if (paniniBaseId == null) {
            return OutDTO.error500("参数为空!");
        }
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        List<GoodsActRecord> actList = groupApiService.getUserListAct(paniniBaseId.longValue());
        List<UserCollectListDTO> userActList = null;
        boolean isActNum = false;
        long userSelectNum = 0;
        long frozenNum = 0;
        if (!CollectionUtils.isEmpty(actList)) {
            GoodsActRecord act = actList.get(0);
            String actType = act.getActType();
            isActNum = Constants.LIST_ACT_SELECT_NUM.equals(actType);
            if (isActNum) {
                userSelectNum = appActService.getUserPointByType(user.getId(), act.getActConfig().getExchangeActType());
                frozenNum=groupApiService.getUserFrozenGoodsNum(user.getId(),paniniBaseId);
                actList.forEach(a -> a.setExchangedAble(appActService.isActExchangeAble(user.getId(), a.getId().intValue())));
            } else {
                userActList = groupApiService.getUserCollectGoods(user.getId(), paniniBaseId, actType);
                if (actType.endsWith(Constants.ACT_GOODS_TYPE_PLAYER) && !CollectionUtils.isEmpty(userActList)) {
                    addPlayerData(paniniBaseId, userActList);
                }
            }
        }
        if (!isActNum) {
            actList.forEach(a -> a.setUserListActDTO(appActService.buildUserListActData(user.getId(), paniniBaseId, a.getActType(), a.getId().intValue())));
        }
        return OutDTO.ok().put("actList", actList).put("userActList", userActList).put("userSelectNum", userSelectNum).put("frozenNum",frozenNum);
    }

    private void addPlayerData(Integer paniniBaseId, List<UserCollectListDTO> userActList) {
        Map<String, UserCollectListDTO> playerDataById = groupApiService.selectPlayerRefData(paniniBaseId);
        if (CollectionUtils.isEmpty(playerDataById)) {
            return;
        }
        userActList.forEach(ua -> {
            UserCollectListDTO playerData = playerDataById.get(ua.getPlayerId().toString());
            if (playerData != null) {
                ua.setRc(playerData.getRc());
                ua.setTeamBg(playerData.getTeamBg());
            }
        });
    }

    @ApiLog(title = "获取checklist活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/exchange/list/prize")
    //@ApiVersion(1.0)
    @ApiOperation("获取checklist活动")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER, msg = "操作频繁,请稍后再试!")
    public OutDTO exchangeListPrize(@RequestBody InDto inDto) {
        Integer paniniBaseId = (Integer) inDto.get("paniniBaseId");
        if (paniniBaseId == null) {
            return OutDTO.error500("参数为空!");
        }
        String actType = inDto.getString("actType");
        if (StringUtils.isEmpty(actType)) {
            return OutDTO.error500("参数【actType】为空!");
        }
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("参数【actId】为空!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        appActService.exchangeListPrize(user.getId(), paniniBaseId, actType, actId);
        appActService.delUserListActCache(paniniBaseId.longValue(), user.getId(), actId.longValue());
        return OutDTO.ok();
    }


    @ApiLog(title = "消费达标活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/consume/detail")
    //@ApiVersion(1.0)
    @ApiOperation("消费达标活动")
    public OutDTO consumeActDetail(@RequestBody InDto inDto) {
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        ConsumeActDTO actDTO = appActService.consumeDetailInfo(actId, user.getId());
        return OutDTO.ok().put("act", actDTO);
    }


    @ApiLog(title = "消费达标奖励兑换", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/exchange/consume/prize")
    //@ApiVersion(1.0)
    @ApiOperation("消费达标奖励兑换")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER, msg = "操作频繁,请稍后再试!")
    public OutDTO exchangeConsumePrize(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        String key = "exchange_consume_prize" + user.getId();
        if (redisUtils.hasKey(key)) {
            return OutDTO.error500("操作频繁,请稍后再试!");
        }
        redisUtils.set(key, 1, 10);
        Integer prizeLevel = (Integer) inDto.get("prizeLevel");
        appActService.exchangeConsumePrize(actId, user, prizeLevel);
        redisUtils.del(key);
        return OutDTO.ok();
    }


    @ApiLog(title = "抽卡机详情", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/card/draw/detail")
    @ApiVersion(1.0)
    @ApiOperation("抽卡机详情")
    public OutDTO cardDrawActDetail(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        CardDrawActDTO act = appActService.getCardDrawActDetail(actId);
        Long userPoint = appActService.getUserPointByType(user.getId(), act.getPointType());
        act.setUserPoint(userPoint.doubleValue());
        List<DrawActPrizeDTO> userDrawPrizes = appActService.getUserDrawPrize(null, user.getId(), null, actId, null, null);
        if (!CollectionUtils.isEmpty(userDrawPrizes)) {
            Map<Integer, DrawActPrizeDTO> userPrizeMap = userDrawPrizes.stream().collect(Collectors.toMap(DrawActPrizeDTO::getPrizeId, DrawActPrizeDTO -> DrawActPrizeDTO));
            act.getPrizes().parallelStream().forEach(prize -> {
                DrawActPrizeDTO existPrize = userPrizeMap.get(prize.getPrizeId());
                prize.setTotalNum(existPrize == null ? 0 : existPrize.getTotalNum());
            });
            act.setUserCollectNum(userDrawPrizes.size());
        }
        return OutDTO.ok().put("act", act);
    }


    @ApiLog(title = "抽卡机详情", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/card/draw/detail")
    @ApiVersion(2.4)
    @ApiOperation("抽卡机详情")
    public OutDTO cardDrawActDetailV2(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = new JSONObject();
        reqData.put("actId", actId);
        JSONObject resData = reqSaas(saasBaseUrl + actDetailUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok(resData);
    }


    @ApiLog(title = "抽卡机图鉴查询", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/card/draw/prize")
    @ApiVersion(2.4)
    @ApiOperation("抽卡机图鉴查询")
    public OutDTO getDrawPrize(@RequestBody InDto inDto) {
        CardQuery cardQuery = inDto.buildParam(new CardQuery());
        if (cardQuery.getActId() == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = JSON.parseObject(JSON.toJSONString(cardQuery));
        ResultDTO resData = reqSaasResult(saasBaseUrl + actPrizeUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok().put("actPrize", resData.getData());
    }

    @ApiLog(title = "抽卡机抽卡", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/card/draw")
    @ApiVersion(1.0)
    @ApiOperation("抽卡机抽卡")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER, msg = "操作频繁,请稍后再试!")
    public OutDTO cardDrawByType(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        String type = inDto.getString("type");
        if (StringUtils.isEmpty(type)) {
            return OutDTO.error500("抽卡类型未传!");
        }
        CardDrawActDTO act = appActService.getCardDrawActDetail(actId);
        Date now = new Date();
        if (now.before(act.getStartTime()) || now.after(act.getActOverTime())) {
            return OutDTO.error500("未处于活动有效期内!");
        }
        if (!act.getDrawTypes().contains(type)) {
            return OutDTO.error500("抽卡类型不存在!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        String key = "user_draw_card_act" + user.getId();
        if (redisUtils.hasKey(key)) {
            return OutDTO.error500("操作频繁,请稍后再试!");
        }
        redisUtils.set(key, 1, 10);
        Long userPoint = appActService.getUserPointByType(user.getId(), act.getPointType());
        if (userPoint < act.getPoint()) {
            redisUtils.del(key);
            return OutDTO.error500("积分不足!");
        }
        List<ConsumePrizeDTO> prizeBySubType = appActService.userDrawCardAct(act, type, user);
        redisUtils.del(key);
        return OutDTO.ok().put("prizeByType", prizeBySubType);
    }

    @ApiLog(title = "抽卡机抽卡", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/card/draw")
    @ApiVersion(2.4)
    @ApiOperation("抽卡机抽卡")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER, msg = "操作频繁,请稍后再试!")
    public OutDTO cardDrawByTypeV2(@RequestBody InDto inDto) {
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        String type = inDto.getString("type");
        if (StringUtils.isEmpty(type)) {
            return OutDTO.error500("抽卡类型未传!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        String key = "user_draw_card_act" + user.getId();
        if (redisUtils.hasKey(key)) {
            return OutDTO.error500("操作频繁,请稍后再试!");
        }
        JSONObject reqData1 = new JSONObject();
        reqData1.put("actId", actId);
        JSONObject resData1 = reqSaas(saasBaseUrl + actDetailUrl, reqData1, user.getBaseUserHeader());
        if ("point".equals(resData1.getString("subType"))) {
            Long userPoint = appActService.getUserPointByType(user.getId(), resData1.getString("pointType"));
            if (userPoint < resData1.getIntValue("point")) {
                redisUtils.del(key);
                return OutDTO.error500("积分不足!");
            }
        }
        JSONObject reqData = new JSONObject();
        reqData.put("actId", actId);
        reqData.put("drawType", type);
        JSONObject resData = reqSaas(saasBaseUrl + drawSubmitUrl, reqData, user.getBaseUserHeader());
        DrawOrderDTO drawOrder = JSON.parseObject(resData.toJSONString(), DrawOrderDTO.class);
        if (drawOrder.getActualPayment() != null && drawOrder.getActualPayment().doubleValue() > 0) {
            log.info("抽卡订单待支付:{}", resData);
            redisUtils.del(key);
            return OutDTO.ok(resData);
        } else if (drawOrder.getPoint() != null && drawOrder.getPoint() > 0) {
            AppUserPointRecord pointRecord = new AppUserPointRecord().setType(drawOrder.getPointType()).setChangePoint(-drawOrder.getPoint().longValue())
                    .setUserId(user.getId().longValue()).setOrderId(drawOrder.getId().longValue()).setOrderNo(drawOrder.getOrderNo())
                    .setCreateTime(new Date());
            mineApiService.addUserPoint(pointRecord);
            JSONObject reqData3 = new JSONObject();
            reqData3.put("id", drawOrder.getId());
            reqData3.put("tenantId", 1);
            ResultDTO result = saasForestClient.sendJsonPost(saasBaseUrl + localOrderDrawUrl, user.getBaseUserHeader(), reqData3);
            return OutDTO.ok().put("prizeByType", result.getData()).put("payWay", "free").put("price", 0);
        } else {
            redisUtils.del(key);
            return OutDTO.error500("抽卡异常,请重试!");
        }
    }

    @ApiLog(title = "获取用户抽卡奖品", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/user/draw/prize")
    @ApiVersion(1.0)
    @ApiOperation("查询用户抽卡奖品")
    public OutDTO getUserDrawPrize(@RequestBody InDto inDto) {
        List<String> actTypes = getDrawActTypes();
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        Integer status = (Integer) inDto.get("status");
        status = status == null ? 0 : status;
        List<DrawActPrizeDTO> drawPrizes = appActService.getUserDrawPrize(actTypes, user.getId(), null, null, status, inDto.getString("prizeType"));
        return OutDTO.ok().put("prizeList", drawPrizes);
    }


    @ApiLog(title = "获取用户抽卡奖品", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/user/draw/prize")
    @ApiVersion(2.4)
    @ApiOperation("查询用户抽卡奖品")
    public OutDTO getUserDrawPrizeV2(@RequestBody InDto inDto) {
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("actId为空!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = new JSONObject();
        reqData.put("actId", actId);
        reqData.put("pageNo", inDto.getPageNo());
        reqData.put("pageSize", inDto.getPageSize());
        JSONObject resData = reqSaas(saasBaseUrl + userPrizeUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok(resData);
    }

    private List<String> getDrawActTypes() {
        List<SysDictData> actTypeDict = commonCacheService.getCommonDictData(Constants.USER_DRAW_CARD_ACT, null, Constants.ONE, Constants.USER_DRAW_CARD_ACT, 3600);
        List<String> actTypes;
        if (CollectionUtils.isEmpty(actTypeDict)) {
            actTypes = Collections.singletonList(Constants.ACT_TYPE_DRAW_CARD_GAME);
        } else {
            actTypes = actTypeDict.stream().map(SysDictData::getDictValue).collect(Collectors.toList());
        }
        return actTypes;
    }

    private BigDecimal getActShippingCost() {
        List<SysDictData> actTypeDict = commonCacheService.getCommonDictData(Constants.ACT_BASE_SHIPPING_COST_KEY, null, null,
                Constants.ACT_BASE_SHIPPING_COST_KEY, 3600);
        if (CollectionUtils.isEmpty(actTypeDict)) {
            return Constants.ACT_BASE_SHIPPING_COST;
        }
        return new BigDecimal(actTypeDict.get(0).getDictValue());
    }

    @ApiLog(title = "提交奖品订单,支付运费", businessType = BusinessType.UPDATE)
    @ResponseBody
    @PostMapping(value = "/submit/prize/order")
    @ApiVersion(1.0)
    @ApiOperation("提交奖品订单,支付运费")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER, msg = "操作频繁,请稍后再试!")
    public OutDTO submitPrizeOrder(@RequestBody InDto inDto) {
        String prizeIds = inDto.getString("prizeIds");
        if (StringUtils.isEmpty(prizeIds)) {
            return OutDTO.error500("奖品ID参数缺失!");
        }
        Integer addressId = (Integer) inDto.get("addressId");
        if (addressId == null) {
            return OutDTO.error500("地址信息缺失!");
        }
        List<Integer> prizeIdList = Arrays.stream(prizeIds.split(",")).map(Integer::valueOf).collect(Collectors.toList());
        List<String> actTypes = getDrawActTypes();
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        String key = "user_draw_card_act" + user.getId();
        if (redisUtils.hasKey(key)) {
            return OutDTO.error500("操作频繁,请稍后再试!");
        }
        redisUtils.set(key, 1, 10);
        List<DrawActPrizeDTO> drawPrizes = appActService.getUserDrawPrize(actTypes, user.getId(), prizeIdList, null, 0, null);
        if (CollectionUtils.isEmpty(drawPrizes)) {
            return OutDTO.error500("未查询到符合条件的奖品信息!");
        }
        PrizeOrderParam prizeOrderParam = new PrizeOrderParam().setPrizeIdList(prizeIdList).setActTypes(actTypes).setUser(user)
                .setAddressId(addressId).setUserKey(key).setShippingCost(getActShippingCost()).setDrawPrizes(drawPrizes);
        OrderSubmitDTO order = mallOrderService.submitPrizeOrder(prizeOrderParam);
        redisUtils.del(key);
        return OutDTO.ok().put("order", order);
    }


    @ApiLog(title = "提交奖品订单,支付运费", businessType = BusinessType.UPDATE)
    @ResponseBody
    @PostMapping(value = "/submit/prize/order")
    @ApiVersion(2.4)
    @ApiOperation("提交奖品订单,支付运费")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER, msg = "操作频繁,请稍后再试!")
    public OutDTO submitPrizeOrderV2(@RequestBody InDto inDto) {
        String prizeIds = inDto.getString("prizeIds");
        Object allFlag = inDto.get("allFlag");
        boolean isAll = allFlag != null && (Boolean) allFlag;
        if (StringUtils.isEmpty(prizeIds) && !isAll) {
            return OutDTO.error500("奖品ID参数缺失!");
        }
        Integer addressId = inDto.getIntegerParam("addressId");
        if (addressId == null) {
            return OutDTO.error500("地址信息缺失!");
        }
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("actId缺失!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        TzyShippingAddress address = shippingAddressService.selectUserAddress(user.getId(), addressId);
        if (address == null) {
            return OutDTO.error500("地址信息异常!");
        }
        String key = "user_draw_card_act" + user.getId();
        if (redisUtils.hasKey(key)) {
            return OutDTO.error500("操作频繁,请稍后再试!");
        }
        redisUtils.set(key, 1, 10);
        JSONObject reqData = new JSONObject();
        reqData.put("prizeIds", prizeIds);
        reqData.put("actId", actId);
        reqData.put("allFlag", isAll);
        reqData.put("linkName", address.getLinkname());
        reqData.put("phone", address.getPhone());
        reqData.put("address", address.getAddress() + address.getAddressMore());
        ResultDTO resultDTO = reqSaasResult(saasBaseUrl + drawPrizeSubmitUrl, reqData, user.getBaseUserHeader());
        redisUtils.del(key);
        return OutDTO.ok().put("order", resultDTO.getData());
    }

    private JSONObject reqSaas(String url, JSONObject reqData, Map<String, Object> header) {
        ResultDTO result = saasForestClient.sendJsonPost(url, header, reqData);
        return JSON.parseObject(JSON.toJSONString(result.getData()));
    }

    private ResultDTO reqSaasResult(String url, JSONObject reqData, Map<String, Object> header) {
        return saasForestClient.sendJsonPost(url, header, reqData);
    }


    @ApiLog(title = "获取活动兑换记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/list/exchange/record")
    @ApiOperation("获取活动兑换记录")
    public OutDTO getUserActExchangeRecord(@RequestBody InDto inDto) {
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        List<UserActTimes> userActTimesList = appActService.getUserActExchangeRecord(actId, user.getId());
        return OutDTO.ok().put("records", userActTimesList);
    }


    @ApiLog(title = "获取抽卡记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/order/list")
    @ApiOperation("获取抽卡记录")
    public OutDTO getUserDrawOrder(@RequestBody InDto inDto) {
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        String status = inDto.getString("status");
        String orderType = inDto.getString("orderType");
        String orderSubType = inDto.getString("orderSubType");
        if (StringUtils.isEmpty(status) || StringUtils.isEmpty(orderType) || StringUtils.isEmpty(orderSubType)) {
            return OutDTO.error500("参数为空");
        }
        JSONObject reqData = new JSONObject();
        reqData.put("orderType", orderType);
        reqData.put("status", status);
        reqData.put("orderSubType", orderSubType);
        ResultDTO resultDTO = reqSaasResult(saasBaseUrl + drawOrderListUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok().put("orderPage", resultDTO.getData());
    }

    @ApiLog(title = "获取抽卡订单明细", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/order/detail")
    @ApiOperation("获取抽卡订单明细")
    public OutDTO getUserDrawOrderDetail(@RequestBody InDto inDto) {
        Integer id = inDto.getIntegerParam("id");
        if (id == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = new JSONObject();
        reqData.put("id", id);
        ResultDTO resultDTO = reqSaasResult(saasBaseUrl + drawOrderDetailUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok().put("order", resultDTO.getData());
    }


    @ApiLog(title = "抽卡订单唤起支付", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/order/prepay")
    @ApiOperation("抽卡订单唤起支付")
    public OutDTO drawOrderPrepay(@RequestBody InDto inDto) throws Exception {
        PayReqParam reqParam = inDto.buildParam(new PayReqParam());
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        reqParam.setCreateip(IpUtils.getHostIp()).setUserType(inDto.getUserType()).setUserId(user.getId()).setOrderType("draw");
        if (StringUtils.isNotEmpty(user.getUserCertData())) {
            String userCertData = AESUtil.decryptData(user.getUserCertData(), Constants.AES_USER_PASSWORD);
            JSONObject json = JSON.parseObject(userCertData);
            reqParam.setCertificateNo(json.getString("certNo")).setUserName(json.getString("certName"));

        }
        JSONObject res = reqSaas(saasBaseUrl + drawOrderPrepayUrl, JSON.parseObject(JSON.toJSONString(reqParam)), user.getBaseUserHeader());
        return OutDTO.ok(res);
    }

    @ApiLog(title = "抽卡订单唤起支付", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/order/pay/cat")
    @ApiOperation("抽卡订单唤起支付")
    public OutDTO getOrderPayCat(@RequestBody InDto inDto) {
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = new JSONObject();
        reqData.put("orderType", "draw");
        ResultDTO resultDTO = reqSaasResult(saasBaseUrl + drawPayCatUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok().put("cat", resultDTO.getData());
    }


    @ApiLog(title = "获取奖品信息", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/prize/info")
    @ApiOperation("获取奖品信息")
    public OutDTO getPrizeInfo(@RequestBody InDto inDto) {
        String type = inDto.getString("type");
        Integer prizeId = inDto.getIntegerParam("prizeId");
        if (StringUtils.isEmpty(type) || prizeId == null) {
            return OutDTO.error500("参数缺失");
        }
        OutDTO ok = OutDTO.ok();
        if (Constants.SKU_ACT_TYPE_COUPON.equals(type)) {
            ok.put("prize", cardBaseInfoService.getPrizeInfo(prizeId));
        }
        return ok;
    }

    @ApiLog(title = "查询抽卡机selected类型", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/draw/selected")
    @ApiVersion(2.4)
    @ApiOperation("查询抽卡机selected类型")
    public OutDTO getDrawSelectedType(@RequestBody InDto inDto) {
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("actId为空!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = new JSONObject();
        reqData.put("actId", actId);
        JSONObject resData = reqSaas(saasBaseUrl + drawSelectedUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok(resData);
    }

    @ApiLog(title = "申请修改地址", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.4)
    @PostMapping("/edit/address")
    @ApiOperation("申请修改地址")
    public OutDTO editAddress(@RequestBody InDto inDto) {
        Integer id = inDto.getIntegerParam("id");
        if (id == null) {
            return OutDTO.error500("订单Id缺失!");
        }
        Integer addressId = inDto.getIntegerParam("addressId");
        if (addressId == null) {
            return OutDTO.error500("地址信息缺失!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        TzyShippingAddress address = shippingAddressService.selectUserAddress(user.getId(), addressId);
        if (address == null) {
            return OutDTO.error500("地址信息异常!");
        }
        JSONObject reqData = new JSONObject();
        reqData.put("id", id);
        reqData.put("addressId", addressId);
        reqData.put("linkName", address.getLinkname());
        reqData.put("phone", address.getPhone());
        reqData.put("address", address.getAddress() + address.getAddressMore());
        reqSaasResult(saasBaseUrl + editActOrderAddr, reqData, user.getBaseUserHeader());
        return OutDTO.ok();
    }

    @ApiLog(title = "删除活动订单", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.4)
    @PostMapping("/order/del")
    @ApiOperation("删除活动订单")
    public OutDTO delActOrder(@RequestBody InDto inDto) {
        Integer id = inDto.getIntegerParam("id");
        if (id == null) {
            return OutDTO.error500("订单Id缺失!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = new JSONObject();
        reqData.put("id", id);
        reqSaasResult(saasBaseUrl + delActOrderUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok();
    }

    @ApiLog(title = "活动订单确认收货", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.4)
    @PostMapping("/order/confirm")
    @ApiOperation("活动订单确认收货")
    public OutDTO confirmActOrder(@RequestBody InDto inDto) {
        Integer id = inDto.getIntegerParam("id");
        if (id == null) {
            return OutDTO.error500("订单Id缺失!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        JSONObject reqData = new JSONObject();
        reqData.put("id", id);
        reqSaasResult(saasBaseUrl + confirmActOrderUrl, reqData, user.getBaseUserHeader());
        return OutDTO.ok();
    }

    @ApiLog(title = "删除活动订单", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.4)
    @PostMapping("/order/cancel")
    @ApiOperation("删除活动订单")
    public OutDTO cancelActOrder(@RequestBody InDto inDto) {
        Integer id = inDto.getIntegerParam("id");
        if (id == null) {
            return OutDTO.error500("订单Id缺失!");
        }
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        CardGroupOrderInfo orderInfo = cardGroupOrderInfoService.getOrderByUserAndId(user.getId(), id.longValue());
        if (orderInfo.getStatus() != 100) {
            return OutDTO.error500("订单不可取消!");
        }
        if (Constants.ORDER_TYPE_DRAW.equals(orderInfo.getOrderType()) || Constants.ORDER_TYPE_GIFT_CARD.equals(orderInfo.getOrderType())) {
            mallOrderService.cancelDrawOrder(orderInfo);
        }
        return OutDTO.ok();
    }

    @ApiLog(title = "拼团活动列表", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.4)
    @PostMapping("/info/gift")
    @ApiOperation("拼团活动列表")
    public OutDTO getInfoGiftAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if (user == null) {
            return OutDTO.error500("请先登录!");
        }
        List<SysDictData> typeData = commonCacheService.getCommonDictData(Constants.INFO_GIVE_DRAW, null, "1", Constants.INFO_GIVE_DRAW, 84600);
        if (CollectionUtils.isEmpty(typeData)) {
            return OutDTO.ok();
        }
        SysDictData data = typeData.get(0);
        String paniniBaseId = data.getDictValue();
        long actId = data.getDictSort();
        List<InfoGiveActDTO> acts = groupApiService.getInfoGiftAct(actId, Integer.valueOf(paniniBaseId), user.getId());
        return OutDTO.ok().put("acts", acts);
    }

    @ApiLog(title = "拼团砍一刀活动列表", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/group/amount")
    @ApiOperation("拼团砍一刀活动列表")
    public OutDTO getGroupAmountAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        List<GroupAmountActDTO> acts=appActService.getGroupAmountAct(user.getId(),inDto.getIntegerParam("actId"));
        return OutDTO.ok().put("acts", acts);
    }

    @ApiLog(title = "参与拼团砍一刀", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/group/amount/join")
    @ApiLimitRule(seconds = 5, limitCount = 25, type = LimitRule.ACT, msg = "参数人数太多,请稍后再试!")
    @ApiOperation("参与拼团砍一刀")
    public OutDTO joinGroupAmountAct(@RequestBody InDto inDto) {
        AppUserInfoDto user = mineApiService.checkUserNew(inDto);
        Integer actId = inDto.getIntegerParam("actId");
        if(actId==null){
            return OutDTO.error500("活动Id缺失!");
        }
        AmountActResult result=appActService.joinGroupAmountAct(user,actId,inDto.getIntegerParam("shareUserId"));
        return OutDTO.ok().put("actResult", result);
    }

    @ApiLog(title = "拼团砍一刀邀请记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/group/share/record")
    @ApiOperation("拼团砍一刀邀请记录")
    @SensitiveData
    public OutDTO userShareRecord(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        String actType = inDto.getString("actType");
        actType = StringUtils.isEmpty(actType) ? Constants.ACT_GROUP_DECR_AMOUNT : actType;
        ActCountParam param = new ActCountParam().setUserId(user.getId()).setActType(actType);
        PageInfo<ShareRecordDTO> records=appActService.userShareRecords(param,inDto.getPageNo(),inDto.getPageSize());
        return OutDTO.ok().put("records", records);
    }

    @ApiLog(title = "砍一刀分享回显", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/share/apply")
    @ApiOperation("砍一刀分享回显")
    public OutDTO userApplyShare(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        Integer actId = inDto.getIntegerParam("actId");
        AmountActResult shareResult = appActService.userApplyShare(actId, user);
        return OutDTO.ok().put("shareResult",shareResult);
    }

    @ApiLog(title = "分享code查询", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/share/search")
    @ApiOperation("分享code查询")
    public OutDTO searchUserShare(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        String code = inDto.getString("code");
        if(StringUtils.isEmpty(code)){
            return OutDTO.error500("code缺失!");
        }
        GroupAmountActDTO act=appActService.getActByShareCode(user.getId(),code);
        return OutDTO.ok().put("act",act);
    }

    @ApiLog(title = "拼团砍一刀弹窗户", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/group/popup")
    @ApiOperation("拼团砍一刀弹窗户")
    public OutDTO getGroupPopupAct(@RequestBody InDto inDto) {
        return OutDTO.ok().put("act",null);
    }

    @ApiLog(title = "拼团砍一刀弹窗户", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/v2/group/popup")
    @ApiOperation("拼团砍一刀弹窗户")
    public OutDTO getGroupPopupActV2(@RequestBody InDto inDto) {
        ActPopUpDTO act = appActService.getGroupPopupAct();
        return OutDTO.ok().put("act", act);
    }

    @ApiLog(title = "活动商品拆卡报告", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/sku/report")
    @ApiOperation("活动商品拆卡报告")
    public OutDTO getActSkuReport(@RequestBody InDto inDto) {
        String actType = inDto.getString("actType");
        actType = StringUtils.isEmpty(actType) ? Constants.ACT_CARD_REMOVAL : actType;
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        boolean limitStatus = !UserType.USER_ROLE_ADMIN.equals(user.getRoleCode());
        List<ActReportDTO> reports = appActService.getActSkuReport(actType, user.getId(), limitStatus, inDto.getOffset(), inDto.getPageSize());
        return OutDTO.ok().put("reports",reports);
    }

    @ApiLog(title = "活动商品拆卡报告", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/sku/report/like")
    @ApiOperation("活动商品拆卡报告")
    public OutDTO getLikeActSkuReport(@RequestBody InDto inDto) {
        String actType = inDto.getString("actType");
        actType = StringUtils.isEmpty(actType) ? Constants.ACT_CARD_REMOVAL : actType;
        List<ActReportDTO> reports=appActService.getLikeActSkuReport(actType, inDto.getPageSize());
        return OutDTO.ok().put("reports",reports);
    }

    @ApiLog(title = "精选卡密赠品", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @RequireRoles(UserType.USER_ROLE_ADMIN)
    @PostMapping("/sku/report/prize")
    @ApiOperation("精选卡密赠品")
    public OutDTO sendLikeReportPrize(@RequestBody InDto inDto) {
        Integer orderId = inDto.getIntegerParam("orderId");
        Integer prizeId = inDto.getIntegerParam("prizeId");
        //购买资格类型 reduction_buy_num
        String prizeType = inDto.getStringDefault("prizeType",Constants.SKU_TYPE_GOODS);
        //购买资格
        Integer reductionNum = inDto.getIntegerDefault("reductionNum", 1);
        if (prizeId == null) {
            List<SysDictData> dataList = commonCacheService.getCommonDictData("act_report_prize", null, "1", "act_report_prize", 3600);
            if (CollectionUtils.isEmpty(dataList)) {
                return OutDTO.error500("未配置赠品!");
            }
            prizeId = Integer.valueOf(dataList.get(0).getDictValue());
        }
        appActService.sendLikeReportPrize(orderId.longValue(), prizeId,prizeType,reductionNum);
        return OutDTO.ok();
    }

    @ApiLog(title = "砍一刀红包", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(2.6)
    @PostMapping("/amount/gift")
    @ApiOperation("砍一刀红包")
    public OutDTO getActGiftAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppAssert.notNull(user, MsgConstants.NEED_LOGIN);
        List<InfoGiveActDTO> acts = groupApiService.getInfoGiftActByRef(user.getId());
        return OutDTO.ok().put("acts", acts);
    }


    @ApiLog(title = "首页红包-字典表发放", businessType = BusinessType.SEARCH)
    @ApiOperation("首页红包-字典表发放")
    @ResponseBody
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @ApiVersion(3.0)
    @PostMapping("/home/draw")
    public OutDTO getHomeDrawAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppAssert.notNull(user, MsgConstants.NEED_LOGIN);
        List<AppActManageDTO> acts=appActService.getHomeDrawAct(user.getId());
        return OutDTO.ok().put("acts", acts);
    }

    @ApiLog(title = "首页红包-字典表发放", businessType = BusinessType.SEARCH)
    @ApiOperation("首页红包-字典表发放")
    @ResponseBody
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @ApiVersion(4.5)
    @PostMapping("/home/draw")
    public OutDTO getHomeDrawAct45(@RequestBody InDto inDto) {
        return OutDTO.error(404,"4.5版本已下线");
    }

    @ApiLog(title = "首页红包-字典表发放", businessType = BusinessType.SEARCH)
    @ApiOperation("首页红包-字典表发放")
    @ResponseBody
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @ApiVersion(4.6)
    @PostMapping("/home/draw")
    public OutDTO getHomeDrawAct46(@RequestBody InDto inDto) {
        return OutDTO.error(404,"4.6版本已下线");
    }

    @ApiLog(title = "首页红包-字典表发放", businessType = BusinessType.SEARCH)
    @ApiOperation("首页红包-字典表发放")
    @ResponseBody
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @ApiVersion(4.7)
    @PostMapping("/home/draw")
    public OutDTO getHomeDrawAct47(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppAssert.notNull(user, MsgConstants.NEED_LOGIN);
        List<AppActManageDTO> acts=appActService.getHomeDrawAct(user.getId());
        return OutDTO.ok().put("acts", acts);
    }

    //region 2025-618活动

    @ApiLog(title = "2025-618砍一刀活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @ApiVersion(3.8)
    @PostMapping("/group/amount")
    @ApiOperation("2025-618活动拼团砍一刀商品秒杀抢拍")
    public OutDTO getGroupGoodsBidAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        List<GroupAmountActDTO> acts = appActService.getGroupAmountActV2(user.getId(),inDto.getIntegerParam("actId"));
        return OutDTO.ok().put("acts", acts);
    }

    @ApiLog(title = "2025-618看视频领优惠活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @PostMapping("/watch/video")
    @ApiOperation("2025-618看视频领优惠活动")
    public OutDTO getWatchVideoAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppActManage act = appActService.getWatchVideoAct(user.getId());
        boolean isComplete =appActService.isVideoTaskComplete(act.getRuleConfig());
        boolean isPrizeSent =appActService.isActTaskPrizeSent(user,act);
        return OutDTO.ok().put("acts", act).put("completed",isComplete).put("prizesent",isPrizeSent);
    }

    @ApiLog(title = "2025-618看视频领优惠活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @PostMapping("/watch/complete")
    @ApiOperation("用户看完视频记录")
    public OutDTO setWatchComplete(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppActManage act = appActService.setWatchComplete(user,inDto.getString("videoId"));
        if(act==null){
            return OutDTO.ok();
        }
        boolean isComplete =appActService.isVideoTaskComplete(act.getRuleConfig());
        boolean isPrizeSent =appActService.isActTaskPrizeSent(user,act);
        return OutDTO.ok().put("acts", act).put("completed",isComplete).put("prizesent",isPrizeSent);
    }

    @ApiLog(title = "2025-618领红包优惠活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @PostMapping("/coupon/list")
    @ApiOperation("2025-618领红包优惠活动")
    public OutDTO getCouponListAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        List<AppActManage> acts = appActService.getCouponFetchActList(user);
        boolean hasnoInterrupt = appActService.checkInterrupt(user,acts);
        Integer totalFetch = 0;
        Integer totalUsed = 0;
        Integer totalProgress = 0;
        for (AppActManage act : acts) {
            if(act.isPrizeFetched()){totalFetch += 1;}
            if(act.isPrizeUsed()){totalUsed +=1;}
            totalProgress = totalUsed;
        }
        return OutDTO.ok().put("acts", acts).put("hasInterrupt",!hasnoInterrupt).put("totalFetch",totalFetch).put("totalUsed",totalUsed).put("totalProgress",totalProgress);
    }

    @ApiLog(title = "2025-618领红包优惠活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @PostMapping("/coupon/fetch")
    @ApiOperation("2025-618领红包")
    public OutDTO getCouponFetchAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        List<AppActManage> actsFetch = appActService.getCouponFetchAct(user,inDto.getIntegerParam("actId"));
        return OutDTO.ok();
    }

    @ApiLog(title = "2025-618完善用户信息优惠活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @PostMapping("/complete/profile")
    @ApiOperation("2025-618完善用户信息优惠活动")
    public OutDTO getCompleteProfileAct(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppActManage act = appActService.getCompleteProfileAct(user.getId());
        boolean isComplete =appActService.isProfileTaskComplete(act.getRuleConfig());
        boolean isPrizeSent =appActService.isActTaskPrizeSent(user,act);
        return OutDTO.ok().put("acts", act).put("completed",isComplete).put("prizesent",isPrizeSent);
    }
    @ApiLog(title = "2025-618完善用户信息优惠活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @PostMapping("/complete/type")
    @ApiOperation("2025-618完善用户信息优惠活动")
    public OutDTO setCompleteProfileType(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppActManage act = appActService.setCompleteProfileType(user,inDto.getString("type"));
        if(act==null){
            return OutDTO.ok();
        }
        boolean isComplete =appActService.isProfileTaskComplete(act.getRuleConfig());
        boolean isPrizeSent =appActService.isActTaskPrizeSent(user,act);
        return OutDTO.ok().put("acts", act).put("completed",isComplete).put("prizesent",isPrizeSent);
    }

    @ApiLog(title = "2025-618用户领取活动优惠", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.USER, msg = "请勿频繁操作")
    @PostMapping("/get/prize")
    @ApiOperation("2025-618用户领取活动优惠")
    public OutDTO getActPrize(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo(true);
        AppActManage act = appActService.getActPrize(user,inDto.getIntegerParam("actId"));
        if(act.getType()=="complete_profile"){
            boolean isComplete =appActService.isProfileTaskComplete(act.getRuleConfig());
            boolean isPrizeSent =appActService.isActTaskPrizeSent(user,act);
            return OutDTO.ok().put("acts", act).put("completed",isComplete).put("prizesent",isPrizeSent);
        } else if (act.getType()=="watch_video") {
            boolean isComplete =appActService.isVideoTaskComplete(act.getRuleConfig());
            boolean isPrizeSent =appActService.isActTaskPrizeSent(user,act);
            return OutDTO.ok().put("acts", act).put("completed",isComplete).put("prizesent",isPrizeSent);
        }
        return OutDTO.ok().put("acts", act);
    }


    @ApiLog(title = "拼团砍一刀弹窗户", businessType = BusinessType.SEARCH)
    @ResponseBody
    @ApiVersion(3.8)
    @PostMapping("/group/popup")
    @ApiOperation("拼团砍一刀弹窗户")
    public OutDTO getGroupPopupActV3(@RequestBody InDto inDto) {
        ActPopUpDTO act = appActService.getGroupPopupActV2();
        return OutDTO.ok().put("act", act);
    }
    //endregion

    //region 2025抽取拉卜卜活动

    @ApiLog(title = "今天是否能参与labubu活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/today", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("今天是否能参与labubu活动")
    @ApiLimitRule(seconds = 1, limitCount = 5, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeToday(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        inDto.setUserId(user.getId());
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        Boolean verifyUserActJoin = true;
        Boolean completeOrderActJoin = true;
        Boolean verifyUserActJoinRecord = true;
        Boolean completeOrderActJoinRecord = true;
        //检查今日已参加过
        verifyUserActJoin = appActService.checkCurrentDayActJoin("verify_user_act",user.getId());
        verifyUserActJoinRecord = verifyUserActJoin;
        if(!verifyUserActJoin){
            //没参加过检查实名状态
            if(userInfo.getFaceVerify()<=0
                    //||!userInfo.getPayInfoFlag()
            ){
                verifyUserActJoin = true;
            }
        }
        //检查今日已参加过
        completeOrderActJoin = appActService.checkCurrentDayActJoin("complete_order_act",user.getId());
        completeOrderActJoinRecord = completeOrderActJoin;
        if(!completeOrderActJoin){
            //没参加过检查消费达标
            completeOrderActJoin = !appActService.checkCurrentDayCompleteOrder(user.getId());
        }
        return OutDTO.ok("verify_user_act/complete_order_act 为true能参加活动").put("verify_user_act", !verifyUserActJoin).put("complete_order_act",
                !completeOrderActJoin).put("verify_user_act_joined", verifyUserActJoinRecord).put("complete_order_act_joined",
                completeOrderActJoinRecord);
    }

    @ApiLog(title = "参与兑换拉卜卜活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange", method = RequestMethod.POST)
    @ApiVersion(4.1)
    @ApiOperation("参与兑换拉卜卜活动")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubu(@RequestBody InDto inDto) {
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        Integer purchaseCount = (Integer) inDto.get("purchaseCount");
        if (purchaseCount == null || purchaseCount < 1) {
            return OutDTO.error500("兑换数量异常!");
        }
        Boolean anonymous = (Boolean) inDto.get("anonymous");
        int isShow = anonymous != null && anonymous ? 0 : 1;
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }

        if(act.getType().equals("verify_user_act")) {
            //检查用户是否实名并且今天是否参加过
            if(userInfo.getFaceVerify()<=0
                //||!userInfo.getPayInfoFlag()
            ){
                return OutDTO.error500("未实名用户不能参加!");
            }
            Boolean verifyUserActJoin = appActService.checkCurrentDayActJoin("verify_user_act",userInfo.getId());
            if(verifyUserActJoin){
                return OutDTO.error500("今天已经参加过了!");
            }
            AppUserPointRecord pointRecord = new AppUserPointRecord();
            pointRecord.setChangePoint(100L);
            pointRecord.setType("verify_user_act");
            pointRecord.setCreateTime(new Date());
            pointRecord.setMerchantId(act.getMerchantId());
            pointRecord.setUserId(userInfo.getId().longValue());
            pointRecord.setRefId(actId+""+userInfo.getId());
            mineApiService.addUserPoint(pointRecord);
        }
        if(act.getType().equals("complete_order_act")) {
            //检查用户今天下单达标并且今天是否参加过
            Boolean todayCompleteOrder = appActService.checkCurrentDayCompleteOrder(userInfo.getId());
            if(!todayCompleteOrder){
                return OutDTO.error500("今天未达到兑换条件!");
            }
            Boolean completeOrderActJoin = appActService.checkCurrentDayActJoin("complete_order_act",userInfo.getId());
            if(completeOrderActJoin){
                return OutDTO.error500("今天已经参加过了!");
            }
            AppUserPointRecord pointRecord = new AppUserPointRecord();
            pointRecord.setChangePoint(100L);
            pointRecord.setType("complete_order_act");
            pointRecord.setCreateTime(new Date());
            pointRecord.setMerchantId(act.getMerchantId());
            pointRecord.setUserId(userInfo.getId().longValue());
            pointRecord.setRefId(actId+""+userInfo.getId());
            mineApiService.addUserPoint(pointRecord);
        }
        if(act.getType().equals("verify_user_act")||act.getType().equals("complete_order_act")){
            appActService.luckPointExchange(actId, 1, userInfo, isShow,true);
        }
        else{
            appActService.luckPointExchange(actId, purchaseCount, userInfo, isShow,true);
        }

        return OutDTO.ok();
    }

    //endregion

    //region labubu 活动2.0 支持活动下添加任务
    /// 传入字典类型时，根据字典查询出所有的几分类型，再根据活动绑定的积分类型查询出活动列表
    /// 如果传入字典键值则查询出键值对应的活动
    @ApiLog(title = "根据字典类型获取绑定过此奖品的所有活动列表", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("根据字典类型获取绑定过此奖品的所有活动列表")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2(@RequestBody InDto inDto) {
        List<AppActManage> acts = new ArrayList<>();
        String actType =inDto.getString("actDicType");
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        if(actType!=null){
            List<SysDictData> sysDictDatas = commonCacheService.getCommonDictData("lucky_point",
                    null,"1", null, -1);
            List<SysDictData> result = sysDictDatas.stream()
                    .filter(data -> actType.equals(data.getRemark()))
                    .collect(Collectors.toList());
            acts = appActService.getActListByPointType(result.stream().map(SysDictData::getDictValue).collect(Collectors.toList()));
        }
        else{
                acts = appActService.getAppActManage("act_task",false);
        }

        if(acts==null||acts.size()<=0){
            return OutDTO.error500("活动不存在!");
        }
        for (AppActManage act:acts) {
            appActService.getActTaskTotalAmount(user,act.getId().intValue());
        }
        acts.sort((a, b) -> Long.compare(b.getId(), a.getId()));
        return OutDTO.ok().put("acts",acts);
    }

    //获取活动和活动中的所有任务
    @ApiLog(title = "获取活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/act", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("获取活动和活动中的所有任务")
    @ApiLimitRule(seconds = 1, limitCount = 20, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2Act(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        inDto.setUserId(user.getId());
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        //此活动的总参与次数
        int totalPoint = appActService.getActTaskTotalPoint(user,actId);
        //已点亮
        List<AppActTaskPrizeRecord> joinedList = appActService.getJoinedPoint(actId,user.getId());
        //剩余点亮数
        List<AppActTaskPrizeRecord> notJoinList = appActService.getNotJoinedPoint(actId,user.getId());
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        AppActManage refAct = appActService.getAppActManageAllStatusByID(act.getRefActId());
        return OutDTO.ok().put("act",act).put("refAct",refAct).put("joinedList",joinedList).put("notJoinList",notJoinList).put("remainPoint",notJoinList.size()).put("totalPoint",totalPoint).put("joinedPoint",joinedList.size());
    }

    //获取活动和活动中的所有任务
    @ApiLog(title = "获取活动和活动中的所有任务", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/tasks", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("获取活动和活动中的所有任务")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2AllTasks(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        //查询当前活动下的所有任务
        List<AppActTaskManage> appActTasks = appActService.getActTaskList(actId,user);
        if(appActTasks==null||appActTasks.size()<=0){
            return OutDTO.error500("活动下没有任务!");
        }
        appActTasks.sort((a, b) -> Long.compare(b.getId(), a.getId()));
        return OutDTO.ok().put("tasks",appActTasks);
    }

    //兑换抽奖码(点亮)
    @ApiLog(title = "参与兑换拉卜卜活动抽奖次数", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/prize", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("参与兑换拉卜卜活动抽奖次数")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksPize(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        inDto.setUserId(user.getId());
        Integer actId = (Integer) inDto.get("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        if(act.getType().equals("act_task")) {
            //查询当前活动下的所有任务
            List<AppActTaskManage> appActTasks = appActService.getActTaskList(actId,user);
            if(appActTasks==null||appActTasks.size()<=0){
                return OutDTO.error500("活动下没有任务!");
            }
            ActTaskJoinDTO joinDTO = appActService.joinActTask(user,actId,act);
            return OutDTO.ok().put("ActTaskJoin",joinDTO);
        }

        return OutDTO.ok();
    }

    //参与记录
    @ApiLog(title = "查询拉卜卜活动参与记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/record", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("查询拉卜卜活动参与记录")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksRecord(@RequestBody InDto inDto) {
        List<AppActManage> acts = new ArrayList<>();
        String actType =inDto.getString("actDicType");
        if(actType!=null){
            List<SysDictData> sysDictDatas = commonCacheService.getCommonDictData("lucky_point",
                    null,"1", null, -1);
            List<SysDictData> result = sysDictDatas.stream()
                    .filter(data -> actType.equals(data.getRemark()))
                    .collect(Collectors.toList());
            acts = appActService.getActListByPointType(result.stream().map(SysDictData::getDictValue).collect(Collectors.toList()));
        }
        else{
            acts = appActService.getAppActManage("act_task",false);
        }
        if(acts==null||acts.size()<=0){
            return OutDTO.error500("活动不存在!");
        }
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        inDto.setUserId(user.getId());
        //map存储act和对应的records
        Map<Integer,AppActManage> actRecordMap = new HashMap<>();
        for(AppActManage act:acts){
                //查询当前活动下的所有任务
                //List<AppActTaskPrizeRecord> records = appActService.getActPrizeRecordList(act.getId().intValue(),user);
                //actRecordMap.put(act.getId().intValue(),records);
                List<PublicPrizeCodeDTO> records = appActService.getActPointPrizeRecordList(act.getRefActId(),user);
                act.setPrizeCodeList(records);
                actRecordMap.put(act.getId().intValue(),act);

        }
        return OutDTO.ok().put("actRecord",actRecordMap);
    }

    //生成助力分享信息
    @ApiLog(title = "生成助力分享信息", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/share/info", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("生成助力分享信息")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksShareInfo(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        Integer actId = (Integer) inDto.get("actId");
        Integer taskId = (Integer) inDto.get("taskId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        if(act.getType().equals("act_task")) {
            //查询当前活动下的所有任务
            List<AppActTaskManage> appActTasks = appActService.getActTaskList(actId,user);
            if(appActTasks==null||appActTasks.size()<=0){
                return OutDTO.error500("活动下没有任务!");
            }
            Optional<AppActTaskManage> task = appActTasks.stream()
                    .filter(t -> t.getId().equals(taskId))
                    .findFirst();
            if (task.isPresent()) {
                ShareActResult shareActResult = new ShareActResult();
                shareActResult = appActService.getUserShareActResult(user,actId,task.get());
                return OutDTO.ok().put("shareActResult",shareActResult);
            } else {
                return OutDTO.error500("活动不存在!");
            }

        }
        return OutDTO.ok();
    }

    //校验助力分享信息并发送奖励
    @ApiLog(title = "校验助力分享信息并发送奖励", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/share/check", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("校验助力分享信息并发送奖励")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksShareCheck(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        Integer actId = (Integer) inDto.get("actId");
        Integer taskId = (Integer) inDto.get("taskId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        String code = inDto.getString("code");
        if(act.getType().equals("act_task")) {
            //查询当前活动下的所有任务
            List<AppActTaskManage> appActTasks = appActService.getActTaskList(actId,user);
            if(appActTasks==null||appActTasks.size()<=0){
                return OutDTO.error500("活动下没有任务!");
            }
            Optional<AppActTaskManage> task = appActTasks.stream()
                    .filter(t -> t.getId().equals(taskId))
                    .findFirst();
            if (task.isPresent()) {
                ShareActResult shareActResult = appActService.getShareActResult(code);
                appActService.checkUserShareActResult(user,actId,task.get(),shareActResult);
                return OutDTO.ok().put("shareActResult",shareActResult);
            } else {
                return OutDTO.error500("活动不存在!");
            }

        }
        return OutDTO.ok();
    }

    //执行助力
    @ApiLog(title = "执行助力", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/share/apply", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("执行助力")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksShareApply(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        String code = inDto.getString("code");
        try {
            appActService.applyActTaskShareRecord(user,code);
            return OutDTO.ok("助力成功!");
        }catch (ServiceException e){
            log.error("助力失败: {}", e.getMessage());
            return OutDTO.error500("助力失败!"+e.getMessage());
        }
    }

    //参与助力邀请记录
    @ApiLog(title = "参与助力邀请记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/share/apply/record", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("参与助力邀请记录")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksShareApplyRecord(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        Integer actId = (Integer) inDto.get("actId");
        Integer taskId = (Integer) inDto.get("taskId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        if(act.getType().equals("act_task")) {
            //查询当前活动下的所有任务
            List<AppActTaskPrizeRecord> record = appActService.getActPrizeShareApplyRecordList(actId,taskId,user.getId());
            return OutDTO.ok().put("record",record);
        }

        return OutDTO.ok();
    }

    //分享记录
    @ApiLog(title = "分享记录", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/share/record", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("分享记录")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksShareRecord(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        Integer actId = (Integer) inDto.get("actId");
        Integer taskId = (Integer) inDto.get("taskId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        if(act.getType().equals("act_task")) {
            //查询当前活动下的所有任务
            List<AppActTaskPrizeRecord> record = appActService.getActPrizeShareRecordList(actId,taskId,user.getId());
            return OutDTO.ok().put("record",record);
        }

        return OutDTO.ok();
    }

    //参与助力分享h5回显
    @ApiLog(title = "参与助力后信息展示", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/share/disp", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("参与助力后信息展示")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksShareDisp(@RequestBody InDto inDto) {
        String code = inDto.getString("code");
        ShareActResult shareActResult = appActService.getShareActResult(code);
        AppActManage act = appActService.getAppActManageByID(shareActResult.getActId());
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        return OutDTO.ok().put("act",act).put("shareInfo",shareActResult);
    }


    //参与签到活动
    @ApiLog(title = "参与签到活动", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/checkin", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("参与签到活动")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,兑换人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksCheckIn(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        Integer actId = (Integer) inDto.get("actId");
        Integer taskId = (Integer) inDto.get("taskId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        if(act.getType().equals("act_task")) {
            //查询当前活动下的所有任务
            List<AppActTaskManage> appActTasks = appActService.getActTaskList(actId,user);
            if(appActTasks==null||appActTasks.size()<=0){
                return OutDTO.error500("活动下没有任务!");
            }
            Optional<AppActTaskManage> task = appActTasks.stream()
                    .filter(t -> t.getId().equals(taskId) )
                    .findFirst();
            if (task.isPresent()) {
                try {
                    appActService.joinActTaskCheckIn(user,actId,task.get());
                    return OutDTO.ok();
                }catch (ServiceException e){
                    log.error("失败: {}", e.getMessage());
                    return OutDTO.error500("签到失败!"+e.getMessage());
                }

            } else {
                return OutDTO.error500("活动不存在!");
            }

        }
        return OutDTO.ok();
    }

    @ApiLog(title = "大转盘抽奖", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/luckDraw", method = RequestMethod.POST)
    @ApiVersion(1.0)
    @ApiOperation("大转盘抽奖")
    @ApiLimitRule(seconds = 1, limitCount = 1, type = LimitRule.USER,lockCount = 3,lockTime = 120,msg = "操作频繁,请稍后再试!")
    public OutDTO labubuLuckDraw(@RequestBody InDto inDto) {
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        //已点亮
        List<AppActTaskPrizeRecord> joinedList = appActService.getJoinedPoint(actId,user.getId());
        AppUserInfoDto userInfo = mineApiService.checkUserNew(inDto);
        AppActPrizeDTO userPrize = appActService.drawTaskPrize(actId, userInfo, joinedList);
        return OutDTO.ok().put("userPrize", userPrize);
    }
    //endregion

    //region 浏览指定页面时长
    //浏览指定页面时长
    @ApiLog(title = "浏览指定页面时长", businessType = BusinessType.SEARCH)
    @ResponseBody
    @RequestMapping(value = "/luck/point/exchange/labubu/task/view/page", method = RequestMethod.POST)
    @ApiVersion(4.3)
    @ApiOperation("浏览指定页面时长")
    @ApiLimitRule(seconds = 1, limitCount = 10, type = LimitRule.COMMON, msg = "抱歉,参与人数太多,请稍后再试!")
    public OutDTO luckPointExchangeLabubuV2TasksViewPage(@RequestBody InDto inDto) {

        Integer actId = inDto.getIntegerParam("actId");
        if (actId == null) {
            return OutDTO.error500("活动参数未传!");
        }
        Integer taskId = (Integer) inDto.get("taskId");
        if (taskId == null) {
            return OutDTO.error500("任务参数未传!");
        }
        //校验用户参数上报的浏览地址是否存在
        String pageUrl = inDto.getString("pageUrl");
        if (StringUtils.isBlank(pageUrl)) {
            return OutDTO.error500("页面参数未传!");
        }
        //校验用户浏览时长参数是否合法
        Integer viewTime = inDto.getIntegerParam("viewTime");
        if (viewTime == null || viewTime <= 0) {
            log.info("浏览时长参数未传,actId: {}, taskId: {}, pageUrl: {}, viewTime: {}", actId, taskId, pageUrl, viewTime);
            //return OutDTO.error500("浏览时长参数未传!");
        }
        AppActManage act = appActService.getAppActManageByID(actId);
        if(act==null){
            return OutDTO.error500("活动不存在!");
        }
        List<AppActTaskManage> appActTasks = appActService.getActTaskList(actId);
        if(appActTasks==null||appActTasks.size()<=0){
            return OutDTO.error500("活动下没有任务!");
        }else {
            if(!appActTasks.stream().anyMatch(t -> t.getId().equals(taskId))){
                return OutDTO.error500("任务不存在!");
            }
        }
        AppActTaskManage task = appActTasks.stream().filter(t -> t.getId().equals(taskId)).findFirst().orElse(null);
        if(task==null){
            return OutDTO.error500("任务不存在!");
        }
        UserInfo user = UserUtils.getSimpleUserInfo();
        if(user==null){
            return OutDTO.error500("请先登陆!");
        }
        //传入用户完成任务的活动id/浏览页地址等，校验是否完成了任务
        try {
            List<AppActTaskPrizeRecord> joinedList = appActService.joinActTaskViewPage(user,act,task,pageUrl,viewTime);
            //根据joinedList 判断appActTasks中是否有已经参与过的任务
            return OutDTO.ok()
                    .put("acts", act)
                    .put("completedTask",appActTasks.stream().filter(t -> joinedList.stream().anyMatch(j -> j.getTaskId().intValue()==(t.getId()))).collect(Collectors.toList()))
                    .put("uncompletedTask",appActTasks.stream().filter(t -> !joinedList.stream().anyMatch(j -> j.getTaskId().intValue()==(t.getId()))).collect(Collectors.toList()));
        }catch (ServiceException e){
            log.error("失败: {}", e.getMessage());
            return OutDTO.error500("浏览时长校验失败!"+e.getMessage());
        }
    }

    //endregion
}
