package com.fzm.mall.server.admin.marketing.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fzm.mall.server.admin.constant.MallResponseError;
import com.fzm.mall.server.admin.exception.MyException;
import com.fzm.mall.server.admin.goods_center.service.ICategoryService;
import com.fzm.mall.server.admin.marketing.entity.dto.PromotionDTO;
import com.fzm.mall.server.admin.marketing.entity.dto.PromotionSaveDTO;
import com.fzm.mall.server.admin.marketing.entity.dto.PromotionUpdateDTO;
import com.fzm.mall.server.admin.marketing.mapper.PromotionMapper;
import com.fzm.mall.server.admin.marketing.model.Promotion;
import com.fzm.mall.server.admin.marketing.model.PromotionRule;
import com.fzm.mall.server.admin.marketing.service.IPromotionCategoryService;
import com.fzm.mall.server.admin.marketing.service.IPromotionRuleService;
import com.fzm.mall.server.admin.marketing.service.IPromotionService;
import com.fzm.mall.server.admin.marketing.service.IPromotionSkuService;
import com.fzm.mall.server.admin.util.CopyUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品促销 服务实现类
 * </p>
 *
 * @author wulixian
 * @since 2021-03-10
 */
@Service
@Transactional
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PromotionServiceImpl extends ServiceImpl<PromotionMapper, Promotion> implements IPromotionService {

    private final PromotionMapper promotionMapper;
    private final IPromotionRuleService promotionRuleService;
    private final IPromotionSkuService promotionSkuService;
    private final IPromotionCategoryService promotionCategoryService;
    private final ICategoryService categoryService;

    @Override
    public void save(PromotionSaveDTO promotionSaveDTO) {
        Promotion promotion = CopyUtil.to(promotionSaveDTO, Promotion.class);
        checkStartTimeAndEndTime(promotion);
        checkVal(promotion);
        promotion.init();

        promotionMapper.insert(promotion);

        promotion.savePromotionRule(promotionRuleService, promotion);

        promotion.savePromotionSku(promotionSkuService, promotion);
        promotion.saveCategory(promotionCategoryService);
    }

    @Override
    public void update(PromotionUpdateDTO promotionUpdateDTO) {
        Promotion promotion = CopyUtil.to(promotionUpdateDTO, Promotion.class);
        checkStartTimeAndEndTime(promotion);
        checkPromotionStarted(promotion);
        checkVal(promotion);

        UpdateWrapper<Promotion> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("promotion_id", promotion.getPromotionId())
                .eq("merchant_id", promotion.getMerchantId())
                .eq("update_time", promotion.getUpdateTime());
        int update = promotionMapper.update(promotion, updateWrapper);
        if (update == 0) {
            throw new MyException(MallResponseError.UPDATE_FAIL);
        }

        promotion.updatePromotionRule(promotionRuleService, promotion);

        promotion.updatePromotionSku(promotionSkuService, promotion);
        promotion.updateCatrgory(promotionCategoryService);
    }

    /**
     * 活动开始时间必须小于结束时间
     *
     * @param promotion
     */
    private void checkStartTimeAndEndTime(Promotion promotion) {
        if (promotion.getEndTime() < promotion.getStartTime()) {
            throw new MyException(MallResponseError.START_TIME_ERROR);
        }
        //同一商户同一时间段只能一个促销活动
        List<Promotion> promotionList = promotionMapper.listTimeRepetition(promotion.getMerchantId());
        List<Promotion> toBeFiltered = promotionList.stream().filter(item -> item.getEndTime() < promotion.getStartTime()
                || item.getStartTime() > promotion.getEndTime() || item.getPromotionId().equals(promotion.getPromotionId())).collect(Collectors.toList());
        promotionList.removeAll(toBeFiltered);

        if(CollectionUtils.isNotEmpty(promotionList)){
            throw new MyException(MallResponseError.PROMATION_TIME_REPETITION);
        }
    }

    /**
     * 只有“未开始”的活动才可编辑
     *
     * @param promotion
     */
    private void checkPromotionStarted(Promotion promotion) {
        QueryWrapper<Promotion> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("promotion_id", promotion.getPromotionId()).eq("merchant_id", promotion.getMerchantId());

        Promotion promotionData = promotionMapper.selectOne(queryWrapper);
        boolean started = promotionData.getStartTime() <= SystemClock.now();
        if (started) {
            throw new MyException(MallResponseError.MARKETING_UPDATE_ERROR);
        }
    }

    @Override
    public void delete(String promotionId, String merchantId) {
        /**
         * 逻辑删除
         */
        Promotion promotion = new Promotion();
        promotion.setPromotionId(promotionId);
        promotion.setStatus(Promotion.PROMOTION_STATUS_DELETED);
        promotion.setMerchantId(merchantId);

        UpdateWrapper<Promotion> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("promotion_id", promotion.getPromotionId())
                .eq("merchant_id", promotion.getMerchantId());
        promotionMapper.update(promotion, updateWrapper);

        promotion.deletePromotionRule(promotionRuleService, promotionId, merchantId);

        promotion.deletePromotionSku(promotionSkuService, promotionId, merchantId);
        promotion.deleteCategory(promotionCategoryService);
    }

    @Override
    public PromotionDTO read(String promotionId, String merchantId) {
        Promotion promotion = promotionMapper.read(promotionId, merchantId);

        promotion.readRule(promotionRuleService, promotionId, merchantId);
        promotion.listSku(promotionSkuService, promotionId, merchantId);
        promotion.listCategory(categoryService);
        return CopyUtil.to(promotion, PromotionDTO.class);
    }

    @Override
    public IPage<PromotionDTO> page(Page<PromotionDTO> page, String promotionId, String name, Integer status, String merchantId) {
        IPage<PromotionDTO> result = promotionMapper.page(page, promotionId, name, status, merchantId);
        return result;
    }

    /**
     * 优惠值不得大于条件值
     * @param promotion
     */
    private void checkVal(Promotion promotion) {
        //4:直降  5: 折扣 跳过检测
        if(promotion.getType().equals(4) || promotion.getType().equals(5)){
            return;
        }
        PromotionRule promotionRule = promotion.getPromotionRule();
        if (promotionRule.getPromotionVal().compareTo(promotionRule.getConditionVal()) == BigDecimal.ROUND_DOWN) {
            throw new MyException(MallResponseError.PREFERENTIAL_TERMS_ERROR);
        }
    }
}
