package com.yonge.cooleshow.biz.dal.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yonge.cooleshow.biz.dal.dao.ActivityPlanStandardDao;
import com.yonge.cooleshow.biz.dal.dao.UserFirstTimeDao;
import com.yonge.cooleshow.biz.dal.dto.ActivityPlanDto;
import com.yonge.cooleshow.biz.dal.dto.ActivityPlanRewardDto;
import com.yonge.cooleshow.biz.dal.dto.search.UserFirstTimeSearch;
import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
import com.yonge.cooleshow.biz.dal.entity.ActivityPlanReward;
import com.yonge.cooleshow.biz.dal.entity.ActivityPlanStandard;
import com.yonge.cooleshow.biz.dal.entity.ActivityRegistration;
import com.yonge.cooleshow.biz.dal.entity.ActivityUserReward;
import com.yonge.cooleshow.biz.dal.entity.UserFirstTime;
import com.yonge.cooleshow.biz.dal.service.ActivityPlanRewardService;
import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
import com.yonge.cooleshow.biz.dal.service.ActivityPlanStandardService;
import com.yonge.cooleshow.biz.dal.service.ActivityRegistrationService;
import com.yonge.cooleshow.biz.dal.service.ActivityRewardService;
import com.yonge.cooleshow.biz.dal.service.ActivityUserRewardService;
import com.yonge.cooleshow.biz.dal.service.UserFirstTimeService;
import com.yonge.cooleshow.biz.dal.vo.ActivityPlanVo;
import com.yonge.cooleshow.common.enums.ActivityTypeEnum;
import com.yonge.cooleshow.common.enums.CacheNameEnum;
import com.yonge.cooleshow.common.enums.ConditionMethodEnum;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.payment.util.DistributedLock;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.joda.time.DateTime;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class ActivityPlanStandardServiceImpl extends ServiceImpl<ActivityPlanStandardDao, ActivityPlanStandard> implements ActivityPlanStandardService {
    private final static Logger log = LoggerFactory.getLogger(ActivityPlanStandardServiceImpl.class);

    @Autowired
    private ActivityPlanService activityPlanService;
    @Autowired
    private ActivityPlanRewardService activityPlanRewardService;
    @Autowired
    private UserFirstTimeService userFirstTimeService;
    @Autowired
    private ActivityRewardService activityRewardService;
    @Autowired
    private ActivityUserRewardService activityUserRewardService;
    @Autowired
    private ActivityRegistrationService activityRegistrationService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private UserFirstTimeDao userFirstTimeMapper;

    @Override
    public boolean createOrUpdate(ActivityPlanDto activityPlan) {
        ActivityPlanStandard planExpand = activityPlan.getPlanStandard();
        if (null == planExpand.getCalculationMethod()) {
            planExpand.setCalculationMethod(ConditionMethodEnum.AND);
        }

        if (null == planExpand.getId()) {
            planExpand.setId(activityPlan.getId());
            planExpand.setCreateBy(activityPlan.getUserId());
            planExpand.setUpdateBy(activityPlan.getUserId());
            saveOrUpdate(planExpand);
        } else {
            planExpand.setUpdateBy(activityPlan.getUserId());
            updateById(planExpand);
        }
        return true;
    }

    @Override
    public void activityIng(Object param) {

        //查询当前进行的活动
        List<ActivityPlan> activityIds = activityPlanService.list(Wrappers.<ActivityPlan>lambdaQuery()
                .eq(ActivityPlan::getActivityType, ActivityTypeEnum.STANDARD_GIFT)
                .eq(ActivityPlan::getActivityState, 1)
                //.ge(ActivityPlan::getActivityEnd, DateTime.now().toDate())
                .select(ActivityPlan::getId));

        for (ActivityPlan activityPlan : activityIds) {
            DistributedLock.of(redissonClient)
                    .runIfLockToFunction(CacheNameEnum.LOCK_ACTIVITY_STOCK.getRedisKey(activityPlan.getId())
                            , this::dealActivityIng, activityPlan.getId(), 10l);
        }
    }

    private Boolean dealActivityIng(Long activityId) {

        ActivityPlanVo detail = activityPlanService.detail(activityId);
        if (null == detail) {
            return true;
        }

        ActivityPlanStandard planStandard = detail.getPlanStandard();
        if (null == planStandard) {
            return true;
        }

        UserFirstTimeSearch search = new UserFirstTimeSearch();
        search.setStartTime(detail.getActivityStart());
        search.setEndTime(detail.getActivityEnd());
        search.setUserType(detail.getActivityClient().getCode());
        search.setCalculationMethod(planStandard.getCalculationMethod());
        search.setTimeType(planStandard.getCondition());

        // 达标活动匹配条件数
        int conditionNum = planStandard.getCondition().split(",").length;

        // 分页查询达标活动匹配用户信息；在根据用户ID查询对应激活时间记录信息
        IPage<UserFirstTime> page = new Page<>(1, 10);
        userFirstTimeMapper.selectActivityParticipateUserPage(page, search.activityId(activityId));

        // 当前匹配条件用户数
        int limit = 30; // 分页行数
        long maxPage = (page.getTotal() - 1) / limit + 1;

        // 分页查询匹配用户信息
        UserFirstTimeSearch query;
        List<Long> userIds;
        for (long pageNum = 1; pageNum <= maxPage; pageNum++) {

            // 匹配用户ID
            userIds = userFirstTimeMapper.selectActivityParticipateUserPage(new Page<>(pageNum, limit),
                            search.activityId(activityId)).stream()
                    .map(UserFirstTime::getUserId).distinct().collect(Collectors.toList());

            if (CollectionUtils.isEmpty(userIds)) {
                continue;
            }

            // 匹配用户查询条件
            query = JSON.parseObject(JSON.toJSONString(search.userIds(userIds)), UserFirstTimeSearch.class);
            //log.info("dealActivityIng query={}", JSON.toJSONString(query));

            // 用户达标活动获奖发送记录
            activityUserSendRewardRecordInfo(userIds, activityId, detail, planStandard, query, conditionNum);
        }

        return true;
    }

    /**
     * 活动用户发奖记录信息
     * @param userIds 发奖用户顺序
     * @param activityId 活动ID
     * @param detail ActivityPlanVo
     * @param planStandard ActivityPlanStandard
     * @param search UserFirstTimeSearch
     * @param conditionNum 达标活动匹配条件
     */
    private void activityUserSendRewardRecordInfo(List<Long> userIds,
                                                  Long activityId,
                                                  ActivityPlanVo detail,
                                                  ActivityPlanStandard planStandard,
                                                  UserFirstTimeSearch search,
                                                  int conditionNum) {
        // 用户激活时间
        Map<Long, List<Long>> userActiveTimeMap = userFirstTimeService.selectAllList(search).stream()
                .collect(Collectors.groupingBy(UserFirstTime::getUserId,
                        Collectors.mapping(x -> new DateTime(x.getTime()).getMillis(), Collectors.toList())));

        if (MapUtils.isEmpty(userActiveTimeMap)) {
            return;
        }

        List<ActivityPlanRewardDto> activityPlanRewardDtos = activityPlanRewardService.queryActivityPlanReward(activityId);

        // 获然用户顺序信息
        List<Long> collect;
        for (Long userId : userIds) {

            collect = userActiveTimeMap.getOrDefault(userId, Lists.newArrayList());
            if (CollectionUtils.isEmpty(collect)) {
                // 没有匹配用户信息
                continue;
            }

            if (ConditionMethodEnum.OR.equals(planStandard.getCalculationMethod())) {

                // 满足其一
                long timestamp = collect.stream().mapToLong(Long::longValue).min().orElse(0L);

                if (timestamp > 0) {
                    //给用户发奖
                    sendUserReward(userId, detail.getId(), new Date(timestamp), activityPlanRewardDtos);
                }

            } else {

                // 全部满足
                long timestamp = collect.stream().mapToLong(Long::longValue).max().orElse(0L);

                if (timestamp > 0 && collect.size() == conditionNum) {
                    //给用户发奖
                    sendUserReward(userId, detail.getId(), new Date(timestamp), activityPlanRewardDtos);
                }
            }
        }

    }

    private void sendUserReward(Long userId, Long activityId, Date winningTime, List<ActivityPlanRewardDto> activityPlanRewardDtos) {

        Date date = DateTime.now().toDate(); // 发奖时间
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            date = formatter.parse(formatter.format(date));
        } catch (ParseException e) {
            log.warn("sendUserReward TIME_CONVERT, userId={}, activityId={}, winningTime={}", userId, activityId, winningTime);
        }

        // 活动关联奖品ID
        List<Long> activityRewardIds = activityPlanRewardDtos.stream()
                .map(ActivityPlanReward::getId).collect(Collectors.toList());

        //给用户发奖
        List<Long> collect = activityRewardService.sendReward(userId, activityId, activityRewardIds, date);

        for (ActivityPlanRewardDto dto : activityPlanRewardDtos) {
            ActivityUserReward userReward = new ActivityUserReward();
            userReward.setActivityId(activityId);
            userReward.setUserId(userId);
            userReward.setRewardId(dto.getRewardId());

            userReward.setGrantFlag(collect.contains(dto.getId()) ? 1 : 0);
            userReward.setWinningTime(winningTime); // 获将时间
            userReward.setCreateTime(date); // 发奖时间

            ActivityUserReward one = activityUserRewardService.getOne(Wrappers.<ActivityUserReward>lambdaQuery()
                    .eq(ActivityUserReward::getUserId, userId)
                    .eq(ActivityUserReward::getActivityId, activityId)
                    .eq(ActivityUserReward::getRewardId, dto.getRewardId()));
            if(null == one){
                activityUserRewardService.save(userReward);
            }
        }

        //若没有报名则给用户报名
        YesOrNoEnum yesOrNoEnum = activityRegistrationService.getRegistration(userId, activityId);
        if (YesOrNoEnum.NO.equals(yesOrNoEnum)) {
            ActivityRegistration registration = new ActivityRegistration();
            registration.setActivityId(activityId);
            registration.setUserId(userId);
            activityRegistrationService.save(registration);
        }
    }

    @Override
    public void successActivity(Long activytyId) {
        //处理活动发奖
        dealActivityIng(activytyId);
        //归还库存
        // activityPlanRewardService.recoveryReward(activytyId);
    }
}