/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.discount.comment.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.app.dto.DiscountDto;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.enums.OfflineHandleEventStatus;
import com.yami.shop.bean.enums.OfflineHandleEventType;
import com.yami.shop.bean.model.OfflineHandleEvent;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.bean.param.ProductParam;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.discount.comment.Enums.DiscountStatusEnum;
import com.yami.shop.discount.comment.dao.DiscountItemMapper;
import com.yami.shop.discount.comment.dao.DiscountMapper;
import com.yami.shop.discount.comment.dao.DiscountProdMapper;
import com.yami.shop.discount.comment.model.Discount;
import com.yami.shop.discount.comment.model.DiscountItem;
import com.yami.shop.discount.comment.model.DiscountProd;
import com.yami.shop.discount.comment.service.DiscountService;
import com.yami.shop.service.OfflineHandleEventService;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/11/21.
 */
@Service
@AllArgsConstructor
public class DiscountServiceImpl extends ServiceImpl<DiscountMapper, Discount> implements DiscountService {

    private final DiscountMapper discountMapper;
    private final DiscountItemMapper discountItemMapper;
    private final DiscountProdMapper discountProdMapper;
    private final OfflineHandleEventService offlineHandleEventService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "DiscountAndItemAndProd", key = "#discount.discountId"),
            @CacheEvict(cacheNames = "DiscountAndItemAndProdByShopId", key = "#discount.shopId")
    })
    public void updateDiscountAndItemAndProd(@Valid Discount discount) {
        Discount discountDB = discountMapper.selectById(discount.getDiscountId());
        if (discountDB.getStatus() > 1 && discount.getStatus() < 2){
            throw new GlobalException("该活动已被平台下线，不能再更改状态");
        }
        discountMapper.updateById(discount);

        discountItemMapper.delete(new LambdaQueryWrapper<DiscountItem>().eq(DiscountItem::getDiscountId, discount.getDiscountId()));

        List<DiscountItem> discountItems = discount.getDiscountItems();
        insertDiscountItems(discount, discountItems);

        discountProdMapper.delete(new LambdaQueryWrapper<DiscountProd>().eq(DiscountProd::getDiscountId, discount.getDiscountId()));

        if (discount.getSuitableProdType() != 0) {
            List<DiscountProd> discountProds = discount.getDiscountProds();
            for (DiscountProd discountProd : discountProds) {
                discountProd.setDiscountId(discount.getDiscountId());
            }
            if (CollectionUtil.isNotEmpty(discountProds)) {
                discountProdMapper.insertDiscountProds(discountProds);
            }
        }
    }

    /**
     * 插入满减项
     * @param discount
     * @param discountItems
     */
    private void insertDiscountItems(@Valid Discount discount, List<DiscountItem> discountItems) {
        for (DiscountItem discountItem : discountItems) {
            if (discountItem.getNeedAmount() == null || discountItem.getDiscount() == null) {
                throw new GlobalException("请填写完整满减信息");
            }
            discountItem.setDiscountId(discount.getDiscountId());
        }
        discountItemMapper.insertDiscountItems(discountItems);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "DiscountAndItemAndProdByShopId", key = "#discount.shopId")
    public void insertDiscountAndItemAndProd(@Valid Discount discount) {
        discountMapper.insert(discount);

        List<DiscountItem> discountItems = discount.getDiscountItems();
        if (CollectionUtil.isEmpty(discountItems)) {
            throw new GlobalException("活动项不能为空，最少要有一个活动项");
        }
        insertDiscountItems(discount, discountItems);
        if (discount.getSuitableProdType() != 0) {
            List<DiscountProd> discountProds = discount.getDiscountProds();
            if (CollectionUtil.isNotEmpty(discountProds)) {
                for (DiscountProd discountProd : discountProds) {
                    discountProd.setDiscountId(discount.getDiscountId());
                }
                discountProdMapper.insertDiscountProds(discountProds);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "DiscountAndItemAndProd", key = "#discountId"),
            @CacheEvict(cacheNames = "DiscountAndItemAndProdByShopId", key = "#shopId")
    })
    public void deleteDiscountsAndItemsAndProds(Long discountId, Long shopId) {
        int i = discountMapper.deleteDiscounts(discountId, shopId);
        if (i > 0) {
            discountItemMapper.delete(new LambdaQueryWrapper<DiscountItem>().eq(DiscountItem::getDiscountId, discountId));
            discountProdMapper.delete(new LambdaQueryWrapper<DiscountProd>().eq(DiscountProd::getDiscountId, discountId));
        }
    }

    @Override
    @Cacheable(cacheNames = "DiscountAndItemAndProd", key = "#discountId")
    public Discount getDiscountAndItemAndProdById(Long discountId) {
        return discountMapper.getDiscountAndItemAndProdById(discountId);
    }

    @Override
    @CacheEvict(cacheNames = "DiscountAndItemAndProd", key = "#discountId")
    public void removeDiscountAndItemAndProdCacheById(Long discountId) {
    }

    @Override
    @Cacheable(cacheNames = "DiscountAndItemAndProdByShopId", key = "#shopId")
    public List<Discount> listDiscountsAndItemsByShopId(Long shopId) {
        return discountMapper.getDiscountsAndItemsByShopId(shopId);
    }

    @Override
    @CacheEvict(cacheNames = "DiscountAndItemAndProdByShopId", key = "#shopId")
    public void removeDiscountsAndItemsCacheByShopId(Long shopId) {
    }

    @Override
    public List<DiscountDto> listByProdId(Long prodId, Long shopId) {
        return discountMapper.listByProdId(prodId,shopId);
    }


    @Override
    public IPage<ProductDto> discountProdList(PageParam<ProductDto> page,Long discountId) {
        return discountMapper.discountProdList(page,discountId);
    }

    @Override
    public IPage<Discount> getPlatformDiscountPage(PageParam<Discount> page, Discount discount) {
        return discountMapper.getPlatformDiscountPage(page, discount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offline(Discount discount, String offlineReason, Long sysUserId) {
        Date now = new Date();
        OfflineHandleEvent offlineHandleEvent = new OfflineHandleEvent();
        offlineHandleEvent.setHandleId(discount.getDiscountId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.DISCOUNT.getValue());
        offlineHandleEvent.setHandlerId(sysUserId);
        offlineHandleEvent.setCreateTime(now);
        offlineHandleEvent.setOfflineReason(offlineReason);
        offlineHandleEvent.setShopId(discount.getShopId());
        offlineHandleEvent.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEvent.setUpdateTime(now);
        offlineHandleEventService.save(offlineHandleEvent);
        // 更新活动状态为下线
        discountMapper.updateStatusByDiscountId(discount.getDiscountId(), DiscountStatusEnum.OFFLINE.getValue());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditApply(Long eventId, Long discountId, String reapplyReason) {
        // 更新活动为待审核状态
        discountMapper.updateStatusByDiscountId(discountId, DiscountStatusEnum.PLATFORM_AUDIT.getValue());
        // 更新事件为待审核
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }


    @Override
    public void auditDiscount(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        // 审核通过
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            // 更新商品状态
            discountMapper.updateStatusByDiscountId(offlineHandleEventAuditParam.getHandleId(), DiscountStatusEnum.CLOSE.getValue());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            discountMapper.updateStatusByDiscountId(offlineHandleEventAuditParam.getHandleId(), DiscountStatusEnum.OFFLINE.getValue());
        }
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }

    @Override
    public IPage<DiscountDto> getDiscountList(PageParam<Discount> page) {
        return discountMapper.getDiscountList(page);
    }

    @Override
    public DiscountDto getDiscountByDiscountId(Long discountId) {
        return discountMapper.getDiscountByDiscountId(discountId);
    }

    @Override
    public void closeDiscountBySetStatus() {
        discountMapper.closeDiscountBySetStatus();
    }

    @Override
    public Integer countProdIsSeckillAll(Long shopId, Long prodId) {
        return discountMapper.countProdIsSeckillAll(shopId,prodId);
    }

    @Override
    public Integer countProdIsSeckillSome(Long shopId, Long prodId) {
        return discountMapper.countProdIsSeckillSome(shopId,prodId);
    }

    @Override
    public Integer countProdIsSeckillExcept(Long shopId, Long prodId) {
        return discountMapper.countProdIsSeckillExcept(shopId,prodId);
    }

    @Override
    public List<Long> getProdIsSeckillExcept(Long shopId) {
        List<DiscountProd> list = discountMapper.getProdIsSeckillExcept(shopId);
        List<Long> prodIds = list.stream().map(t -> t.getProdId()).distinct().collect(Collectors.toList());
        return prodIds;
    }

    @Override
    public IPage<Product> pageProdByDiscount(PageParam<Product> page, ProductParam product, Discount discount) {
        return discountMapper.pageProdByDiscount(page,product,discount);
    }

}
