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.CouponDTO;
import com.fzm.mall.server.admin.marketing.entity.dto.CouponSaveDTO;
import com.fzm.mall.server.admin.marketing.entity.dto.CouponUpdateDTO;
import com.fzm.mall.server.admin.marketing.mapper.CouponMapper;
import com.fzm.mall.server.admin.marketing.model.Coupon;
import com.fzm.mall.server.admin.marketing.service.ICouponCategoryService;
import com.fzm.mall.server.admin.marketing.service.ICouponService;
import com.fzm.mall.server.admin.marketing.service.ICouponSkuService;
import com.fzm.mall.server.admin.util.CopyUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.bind.SchemaOutputResolver;
import java.math.BigDecimal;
import java.util.List;

/**
 * <p>
 * 商品优惠券 服务实现类
 * </p>
 *
 * @author fzm
 * @since 2021-04-13
 */
@Service
@Transactional
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {

    private final CouponMapper couponMapper;
    private final ICouponSkuService couponSkuService;
    private final ICouponCategoryService couponCategoryService;
    private final ICategoryService categoryService;

    @Override
    public List<Coupon> listByOid(String oid, String uid, List<String> goodsIdList) {
        return couponMapper.listByOid(oid, uid, goodsIdList);
    }

    @Override
    public void save(CouponSaveDTO couponSaveDTO) {
        Coupon coupon = CopyUtil.to(couponSaveDTO, Coupon.class);
        checkStartTimeAndEndTime(coupon);
        checkVal(coupon);

        coupon.init();

        coupon.saveCouponSku(couponSkuService);
        coupon.saveCategory(couponCategoryService);

        couponMapper.insert(coupon);
    }

    @Override
    public void update(CouponUpdateDTO couponUpdateDTO) {
        Coupon coupon = CopyUtil.to(couponUpdateDTO, Coupon.class);
        if (!coupon.getType().equals(Coupon.TYPE_TRAVEL)) {
            coupon.setExchangePrice(BigDecimal.ZERO);
        }
        checkStartTimeAndEndTime(coupon);
        checkVal(coupon);
        /**
         * 活动生效时，优惠券不可被更改
         */
        checkCouponStarted(coupon);

        UpdateWrapper<Coupon> wrapper = new UpdateWrapper<>();
        wrapper.eq("coupon_id", coupon.getCouponId())
                .eq("merchant_id", coupon.getMerchantId())
                .eq("update_time", coupon.getUpdateTime());
        int update = couponMapper.update(coupon, wrapper);
        if (update == 0) {
            throw new MyException(MallResponseError.UPDATE_FAIL);
        }

        coupon.updateCouponSku(couponSkuService);

        coupon.updateCategory(couponCategoryService);
    }

    /**
     * 活动开始时间必须小于结束时间
     *
     * @param coupon
     */
    private void checkStartTimeAndEndTime(Coupon coupon) {
        if (coupon.getEndTime() < coupon.getStartTime()) {
            throw new MyException(MallResponseError.START_TIME_ERROR);
        }
    }

    /**
     * 只有“未开始”的活动才可编辑
     *
     * @param coupon
     */
    private void checkCouponStarted(Coupon coupon) {
        QueryWrapper<Coupon> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("coupon_id", coupon.getCouponId()).eq("merchant_id", coupon.getMerchantId());

        Coupon couponData = couponMapper.selectOne(queryWrapper);
        boolean couponStarted = couponData.getStartTime() <= SystemClock.now();
        if (couponStarted) {
            throw new MyException(MallResponseError.MARKETING_UPDATE_ERROR);
        }
    }

    @Override
    public void delete(String couponId, String merchantId) {
        Coupon coupon = new Coupon();
        coupon.setCouponId(couponId);
        coupon.setMerchantId(merchantId);
        coupon.setStatus(Coupon.COUPON_STATUS_DELETED);
        UpdateWrapper<Coupon> wrapper = new UpdateWrapper<>();
        wrapper.eq("coupon_id", coupon.getCouponId())
                .eq("merchant_id", coupon.getMerchantId());
        int update = couponMapper.update(coupon, wrapper);
        if (update == 0) {
            throw new MyException(MallResponseError.UPDATE_FAIL);
        }

        coupon.deleteCouponSku(couponSkuService);

        coupon.deleteCategory(couponCategoryService);
    }

    @Override
    public CouponDTO read(String couponId, String merchantId) {
        QueryWrapper<Coupon> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("coupon_id", couponId).eq("merchant_id", merchantId);

        Coupon coupon = couponMapper.selectOne(queryWrapper);
        coupon.listCouponSku(couponSkuService);
        coupon.listCategory(categoryService);
        return CopyUtil.to(coupon, CouponDTO.class);
    }

    @Override
    public IPage<CouponDTO> page(Page<CouponDTO> page, String couponId, String name, Integer status, String merchantId) {
        IPage<CouponDTO> result = couponMapper.page(page, couponId, name, status, merchantId);
        return result;
    }

    /**
     * 优惠值不得大于条件值
     * @param coupon
     */
    private void checkVal(Coupon coupon) {
        if (coupon.getCouponVal().compareTo(coupon.getConditionVal()) == BigDecimal.ROUND_DOWN) {
            throw new MyException(MallResponseError.PREFERENTIAL_TERMS_ERROR);
        }
    }
}
