package com.webchat.service.lottery;

import com.webchat.common.bean.APIPageResponseBean;
import com.webchat.common.constants.LotteryConstants;
import com.webchat.common.util.IDGenerateUtil;
import com.webchat.domain.vo.request.lottery.LotteryActivitySaveVO;
import com.webchat.domain.vo.request.lottery.LotteryActivityStatusUpdateVO;
import com.webchat.domain.vo.response.lottery.LotteryActivityBaseVO;
import com.webchat.domain.vo.response.lottery.LotteryActivityVO;
import com.webchat.repository.dao.lottery.ILotteryActivityDAO;
import com.webchat.repository.entity.lottery.LotteryActivityEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author 程序员七七
 * @webSite https://www.coderutil.com
 * @Date 2022/11/16 23:40
 * @description
 */
@Slf4j
@Service
public class LotteryActivityService {

    @Autowired
    private LotteryItemService lotteryItemService;
    @Autowired
    private ILotteryActivityDAO lotteryActivityDAO;
    @Autowired
    private LotteryCacheService lotteryCacheService;

    /**
     * 创建或更新抽奖活动
     *
     * @param lotteryActivityVO
     * @param userId
     * @return
     */
    public String save(LotteryActivitySaveVO lotteryActivityVO, String userId) {
        LotteryActivityEntity entity = this.convert(lotteryActivityVO, userId);
        // 保存抽奖活动信息入库
        entity = lotteryActivityDAO.save(entity);
        // 刷新抽奖活动缓存
        lotteryCacheService.refreshLotteryActivityCacheByEntity(entity);
        return entity.getActivityId();
    }

    /**
     * 更新抽奖活动状态
     *
     * @param lotteryActivityStatusUpdate
     * @param userId
     */
    public void updateLotteryActivityStatus(LotteryActivityStatusUpdateVO lotteryActivityStatusUpdate, String userId) {
        String activityId = lotteryActivityStatusUpdate.getActivityId();
        Integer updateStatus = lotteryActivityStatusUpdate.getStatus();
        if (LotteryConstants.LotteryActivityStatus.RUNNING.getStatus().equals(updateStatus)) {
            // 发布活动（进行中）: 校验活动的奖品数量
            lotteryItemService.validateLotteryItemCount(activityId);
        }
        LotteryActivityEntity lotteryActivityEntity = lotteryActivityDAO.findByActivityId(activityId);
        lotteryActivityEntity.setStatus(updateStatus);
        lotteryActivityEntity.setUpdateBy(userId);
        lotteryActivityEntity.setUpdateDate(new Date());
        lotteryActivityDAO.save(lotteryActivityEntity);
        // 刷新抽奖活动缓存
        lotteryCacheService.refreshLotteryActivityCacheByEntity(lotteryActivityEntity);
        log.info("【抽奖活动状态变更】{} 修改抽奖活动 {} 状态为: {}", userId, activityId, updateStatus);
    }

    /**
     * 查询抽奖活动详情
     *
     * @return
     */
    public LotteryActivityVO getLotteryActivityDetailFromCache(String lotteryActivityId) {
        return lotteryCacheService.getLotteryActivityDetailFromCache(lotteryActivityId);
    }

    public LotteryActivityBaseVO getLastLotteryActivityBaseFromCache() {
        String activityId = lotteryCacheService.getLastLotteryActivityIdFromCache();
        return lotteryCacheService.getLotteryActivityDetailFromCache(activityId);
    }

    /**
     * 查询最新一期活动Id
     *
     * @return
     */
    public String getLastLotteryActivityIdFromCache() {
        return lotteryCacheService.getLastLotteryActivityIdFromCache();
    }

    /**
     * 查询历史活动
     * @param lastId
     * @param size
     * @return
     */
    public List<LotteryActivityBaseVO> getHistoryActivityList(Long lastId, int size) {
        lastId = lastId == null ? lastId.MAX_VALUE : lastId;
        return lotteryCacheService.queryHistoryActivityFromCache(lastId, size);
    }


    /**
     * 列表查询
     * @param name
     * @param status
     * @param pageNo
     * @param pageSize
     * @return
     */
    public APIPageResponseBean<List<LotteryActivityBaseVO>> pageList(String name, Integer status, int pageNo, int pageSize) {
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Order.desc("id")));
        Specification<LotteryActivityEntity> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (status != null) {
                predicates.add(criteriaBuilder.equal(root.get("status").as(Integer.class), status));
            }
            if (StringUtils.isNotBlank(name)) {
                predicates.add(criteriaBuilder.like(root.get("name").as(String.class), "%" + name + "%"));
            }
            Predicate[] pre = new Predicate[predicates.size()];
            criteriaQuery.where(predicates.toArray(pre));
            return criteriaQuery.getRestriction();
        });
        Page<LotteryActivityEntity> lotteryActivityEntities = lotteryActivityDAO.findAll(specification, pageable);
        if (CollectionUtils.isEmpty(lotteryActivityEntities.getContent())) {
            return APIPageResponseBean.success(pageNo, pageSize, lotteryActivityEntities.getTotalPages(), Collections.emptyList());
        }
        List<LotteryActivityBaseVO> lotteryActivityBaseVOList = lotteryActivityEntities.getContent().stream().map(la -> {
            LotteryActivityBaseVO lotteryActivityBaseVO = new LotteryActivityVO();
            lotteryActivityBaseVO.setActivityId(la.getActivityId());
            lotteryActivityBaseVO.setCover(la.getCover());
            lotteryActivityBaseVO.setName(la.getName());
            lotteryActivityBaseVO.setIntegral(la.getIntegral());
            lotteryActivityBaseVO.setDescription(la.getDescription());
            lotteryActivityBaseVO.setStatus(la.getStatus());
            lotteryActivityBaseVO.setStatusName(LotteryConstants.getLotteryActivityStatusName(la.getStatus()));
            lotteryActivityBaseVO.setCreateTime(la.getCreateDate().getTime());
            return lotteryActivityBaseVO;
        }).collect(Collectors.toList());
        return APIPageResponseBean.success(pageNo, pageSize, lotteryActivityEntities.getTotalElements(), lotteryActivityBaseVOList);
    }

    private LotteryActivityEntity convert(LotteryActivitySaveVO lotteryActivityVO, String userId) {
        Long id = lotteryActivityVO.getId();
        Date now = new Date();
        LotteryActivityEntity entity;
        if (id != null) {
            entity = lotteryActivityDAO.findById(id).orElse(null);
            Assert.isTrue(entity != null, "更新失败: 活动不存在！");
        } else {
            entity = new LotteryActivityEntity();
            entity.setActivityId(IDGenerateUtil.createId(LotteryConstants.LOTTERY_ACTIVITY_ID_PREFIX));
            // 首次新建: 筹备中
            entity.setStatus(LotteryConstants.LotteryActivityStatus.PREPARATION.getStatus());
            entity.setCreateBy(userId);
            entity.setCreateDate(now);
        }
        entity.setName(lotteryActivityVO.getName());
        entity.setDescription(lotteryActivityVO.getDescription());
        entity.setIntegral(0);
        entity.setCover(lotteryActivityVO.getCover());
        entity.setMoney(lotteryActivityVO.getMoney());
        entity.setUpdateBy(userId);
        entity.setUpdateDate(now);
        return entity;
    }

}
