package com.fzm.mall.server.admin.marketing.model;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import com.fzm.mall.server.admin.goods_center.mapper.SkuMapper;
import com.fzm.mall.server.admin.goods_center.mapper.SpuMapper;
import com.fzm.mall.server.admin.goods_center.model.Category;
import com.fzm.mall.server.admin.goods_center.model.Sku;
import com.fzm.mall.server.admin.goods_center.model.Spu;
import com.fzm.mall.server.admin.goods_center.service.ICategoryService;
import com.fzm.mall.server.admin.marketing.service.ICouponCategoryService;
import com.fzm.mall.server.admin.marketing.service.ICouponSkuService;
import com.fzm.mall.server.admin.util.UUIDUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品优惠券
 * </p>
 *
 * @author fzm
 * @since 2021-04-13
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("marketing_coupon")
@ApiModel(value = "Coupon对象", description = "商品优惠券")
public class Coupon implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 状态 0:删除
     */
    public static final Integer COUPON_STATUS_DELETED = 0;

    /**
     * 状态 1:有效
     */
    public static final Integer COUPON_STATUS_EFFECTIVE = 1;

    /**
     * 状态 2:未开始
     */
    public static final Integer COUPON_STATUS_NOT_STARTED = 2;

    /**
     * 状态 3:已过期
     */
    public static final Integer COUPON_STATUS_EXPIRED = 3;

    public static final Integer TYPE_TRAVEL = 5;

    private Long id;

    @ApiModelProperty(value = "优惠券编号")
    private String couponId;

    @ApiModelProperty(value = "类型  1:满减  2:直减  3: 满折  4:折扣   5:旅游消费")
    private Integer type;

    @ApiModelProperty(value = "优惠券名称")
    private String name;

    @ApiModelProperty(value = "描述")
    private String remark;

    @ApiModelProperty(value = "活动范围 1.全部 2.APP 3.PC 4.微信小程序")
    private Integer scope;

    @ApiModelProperty(value = "范围类型1: 全部  2: 指定类目  3: 指定商品")
    private Integer rangeType;

    @ApiModelProperty(value = "优惠券条件值")
    private BigDecimal conditionVal;

    @ApiModelProperty(value = "优惠值")
    private BigDecimal couponVal;

    @ApiModelProperty(value = "优惠券兑换价格（仅旅游消费）")
    private BigDecimal exchangePrice;

    @ApiModelProperty(value = "发行量  为0表示发行量没有上限")
    private Long circulation;

    @ApiModelProperty(value = "剩余数量")
    private Long amt;

    @ApiModelProperty(value = "开始时间")
    private Long startTime;

    @ApiModelProperty(value = "结束时间")
    private Long endTime;

    @ApiModelProperty(value = "状态 0->不可用;1->可用;2->未开始;3->已过期")
    private Integer status;

    @ApiModelProperty(value = "商户id")
    private String merchantId;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private Long createTime;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateTime;

    @TableField(exist = false)
    @ApiModelProperty(value = "优惠券对应的规格商品")
    private List<CouponSku> couponSkuList;

    @TableField(exist = false)
    @ApiModelProperty(value = "优惠券对应的商品类目")
    private List<Category> categoryList;

    public void init() {
        if (getStartTime() > SystemClock.now()) {
            setStatus(COUPON_STATUS_NOT_STARTED);
        } else if (getEndTime() < SystemClock.now()) {
            setStatus(COUPON_STATUS_EXPIRED);
        } else {
            setStatus(COUPON_STATUS_EFFECTIVE);
        }
        if (!this.type.equals(TYPE_TRAVEL)) {
            setExchangePrice(BigDecimal.ZERO);
        }
        setCouponId(UUIDUtil.getUUID());
        setAmt(circulation);
    }

    public void saveCouponSku(ICouponSkuService couponSkuService, SpuMapper spuMapper, SkuMapper skuMapper) {
        batchSaveCouponSku(this.couponSkuList, couponSkuService, spuMapper, skuMapper);
    }

    public void batchSaveCouponSku(List<CouponSku> paramList, ICouponSkuService couponSkuService, SpuMapper spuMapper, SkuMapper skuMapper) {
        if (CollectionUtils.isEmpty(paramList)) {
            return;
        }
        /**
         * 如果商品销售类型为盲盒，默认勾选盲盒的所有规格（即使前台勾选不完全）
         */
        List<String> goodsIdList = paramList.stream().map(CouponSku::getGoodsId).collect(Collectors.toList());
        QueryWrapper<Spu> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("goods_id", goodsIdList);
        List<Spu> spuList = spuMapper.selectList(queryWrapper);
        List<String> blindBoxSpuIdList = spuList.stream().filter(spu -> spu.getSalesType().equals(Spu.BLIND_BOX_SALES)).map(Spu::getGoodsId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(blindBoxSpuIdList)) {
            List<String> paramSkuIdList = paramList.stream().map(CouponSku::getSkuId).collect(Collectors.toList());

            QueryWrapper<Sku> skuQueryWrapper = new QueryWrapper<>();
            skuQueryWrapper.in("goods_id", goodsIdList);
            List<Sku> dataSkuList = skuMapper.selectList(skuQueryWrapper);
            List<Sku> skuToAddList = dataSkuList.stream().filter(sku -> !paramSkuIdList.contains(sku.getSkuId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(skuToAddList)) {
                skuToAddList.forEach(sku -> {
                    CouponSku couponSku = new CouponSku();
                    couponSku.setSkuId(sku.getSkuId());
                    couponSku.setGoodsId(sku.getGoodsId());
                    paramList.add(couponSku);
                });
            }
        }
        paramList.forEach(couponSku -> {
            couponSku.setMerchantId(this.getMerchantId());
            couponSku.setCouponId(this.getCouponId());
            couponSku.setStatus(CouponSku.COUPON_SKU_STATUS_EFFECTIVE);
        });
        couponSkuService.saveBatch(paramList);
    }

    public void updateCouponSku(ICouponSkuService couponSkuService, SpuMapper spuMapper, SkuMapper skuMapper) {
        List<CouponSku> paramSkuList = this.couponSkuList;
        List<CouponSku> dataSkuList = couponSkuService.list(new QueryWrapper<CouponSku>().eq("coupon_id", this.getCouponId())
                .eq("merchant_id", this.getMerchantId())
                .eq("status", CouponSku.COUPON_SKU_STATUS_EFFECTIVE));

        List<CouponSku> toAddList = paramSkuList.stream().filter(couponSku -> StringUtils.isBlank(couponSku.getCouponId())).collect(Collectors.toList());
        List<CouponSku> reaminList = paramSkuList;
        reaminList.removeAll(toAddList);

        batchSaveCouponSku(toAddList, couponSkuService, spuMapper, skuMapper);

        List<String> reaminCouponIdList = reaminList.stream().map(CouponSku::getGoodsId).collect(Collectors.toList());

        dataSkuList.forEach(couponSku -> {
            if (!reaminCouponIdList.contains(couponSku.getGoodsId())) {
                couponSku.setStatus(CouponSku.COUPON_SKU_STATUS_DELETED);
                couponSkuService.update(couponSku, new UpdateWrapper<CouponSku>().eq("merchant_id", this.getMerchantId())
                        .eq("goods_id", couponSku.getGoodsId()).eq("sku_id", couponSku.getSkuId()));
            }
        });

    }

    public void deleteCouponSku(ICouponSkuService couponSkuService) {
        CouponSku couponSku = new CouponSku();
        couponSku.setCouponId(this.getCouponId());
        couponSku.setMerchantId(this.getMerchantId());
        couponSku.setStatus(CouponSku.COUPON_SKU_STATUS_DELETED);
        UpdateWrapper<CouponSku> wrapper = new UpdateWrapper<>();
        wrapper.eq("coupon_id", this.getCouponId())
                .eq("merchant_id", this.getMerchantId());

        couponSkuService.update(couponSku, wrapper);
    }

    public void listCouponSku(ICouponSkuService couponSkuService) {
        List<CouponSku> couponSkuList = couponSkuService.listSku(couponId, merchantId);
        setCouponSkuList(couponSkuList);
    }

    public void saveCategory(ICouponCategoryService couponCategoryService) {
        if (CollectionUtils.isNotEmpty(this.categoryList)) {
            List<CouponCategory> dataList = this.categoryList.stream().map(category -> {
                CouponCategory couponCategory = new CouponCategory();
                couponCategory.setCategoryId(category.getCategoryId());
                couponCategory.setMerchantId(this.merchantId);
                couponCategory.setCouponId(this.couponId);
                return couponCategory;
            }).collect(Collectors.toList());
            couponCategoryService.saveBatch(dataList);
        }
    }

    public void updateCategory(ICouponCategoryService couponCategoryService) {
        deleteCategory(couponCategoryService);

        saveCategory(couponCategoryService);
    }

    public void deleteCategory(ICouponCategoryService couponSkuService) {
        //先删除中间关系
        QueryWrapper<CouponCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("coupon_id", this.getCouponId())
                .eq("merchant_id", this.getMerchantId());
        couponSkuService.remove(queryWrapper);
    }

    public void listCategory(ICategoryService categoryService) {
        List<Category> categoryList = categoryService.listByCoupon(this.couponId, this.merchantId);
        setCategoryList(categoryList);
    }
}
