package com.yonge.cooleshow.admin.io.request.coupon;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.MK;
import com.yonge.cooleshow.biz.dal.enums.coupon.CouponCategoryEnum;
import com.yonge.cooleshow.biz.dal.enums.coupon.CouponTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.coupon.CouponValidTypeEnum;
import com.yonge.cooleshow.common.enums.EStatus;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.page.QueryInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

/**
 * 优惠券信息
 * Created by Eric.Shang on 2022/9/2.
 */
public class CouponInfoVO {

    /**
     * 优惠券分页请求信息
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("优惠券信息分页请求信息")
    public static class PageRequest extends QueryInfo {

        @ApiModelProperty(value = "优惠券ID", hidden = true)
        private Long couponId;

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

        @ApiModelProperty("客户类型")
        private ClientEnum clientType;

        @ApiModelProperty("优惠券类型")
        private CouponTypeEnum couponType;

        @ApiModelProperty("可用品类")
        private CouponCategoryEnum category;

        @ApiModelProperty("优惠券状态")
        private Integer status;

        @ApiModelProperty(value = "当前时间", hidden = true)
        private Long timestamp;

        @ApiModelProperty(value = "优惠券时间类型", hidden = true)
        private CouponValidTypeEnum validType;

        public String jsonString() {
            return JSON.toJSONString(this);
        }

        public String getName() {

            return Optional.ofNullable(this.name)
                    .filter(x -> StringUtils.isNotEmpty(x) && !x.matches(MK.EXP_INT)).orElse(null);
        }

        public Long getCouponId() {
            if (StringUtils.isNotEmpty(this.name) && this.name.matches(MK.EXP_INT)) {
                return Long.parseLong(this.name);
            }
            return couponId;
        }

        public void setStatus(Integer status) {

            if (EStatus.ENABLE.match(status)) {
                this.timestamp(DateTime.now().getMillis()).setValidType(CouponValidTypeEnum.DAY);
            }
            this.status = status;
        }

        public PageRequest timestamp(Long timestamp) {
            this.timestamp = timestamp;
            return this;
        }
    }

    /**
     * 优惠券分页响应数据
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("优惠券信息分页响应信息")
    public static class CouponPageInfo implements Serializable {

        @ApiModelProperty("优惠券ID")
        private Long id;

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

        @ApiModelProperty("描述")
        private String describe;

        @ApiModelProperty("客户端类型: TEACHER(老师端), STUDENT(学生端)")
        private ClientEnum clientType;

        @ApiModelProperty("可用品类: UNIVERSAL(全场通用) VIP(小酷Ai) PIANO(云酷琴房) MALL(商场购物券) MUSIC(单曲点播券) SPARRING(陪练课购买券) LIVE(直播课购买券) VIDEO(视频课购买券) ")
        private CouponCategoryEnum category;

        @ApiModelProperty("优惠券类型: FULL_DISCOUNT(满减券) VOUCHER(代金券) ")
        private CouponTypeEnum couponType;

        @ApiModelProperty("当前库存量")
        private Integer inventory;

        @ApiModelProperty("领取次数限制")
        private Integer quantityLimit;

        @ApiModelProperty("状态")
        private Integer status;

        @ApiModelProperty("发放领取数")
        private Integer issueNum;

        @ApiModelProperty("关联奖品数")
        private Integer rewardNum;

        @ApiModelProperty("最后更新人")
        private String updatedUser;

        @ApiModelProperty(value = "最后更新时间", hidden = true)
        private Long updateTime;

        @ApiModelProperty("最后更新时间")
        @JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
        private Date updatedTime;

        @ApiModelProperty("创建时间")
        @JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
        private Date createdTime;

        public Date getUpdatedTime() {

            if (Optional.ofNullable(getUpdateTime()).orElse(0L) > 0) {
                return new DateTime(getUpdateTime()).toDate();
            }
            return updatedTime;
        }
    }

    /**
     * 优惠券详情信息
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class CouponQueryInfo implements Serializable {

        @ApiModelProperty("优惠券ID")
        private Long id;

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

        @ApiModelProperty("描述")
        private String describe;

        @ApiModelProperty("客户端类型: TEACHER(老师端), STUDENT(学生端)")
        private ClientEnum clientType;

        @ApiModelProperty("可用品类: UNIVERSAL(全场通用) VIP(小酷Ai) PIANO(云酷琴房) MALL(商场购物券) MUSIC(单曲点播券) SPARRING(陪练课购买券) LIVE(直播课购买券) VIDEO(视频课购买券) ")
        private CouponCategoryEnum category;

        @ApiModelProperty("使用门槛")
        private BigDecimal useLimit;

        @ApiModelProperty("优惠金额")
        private BigDecimal discountPrice;

        @ApiModelProperty("优惠券类型")
        private CouponTypeEnum couponType;

        @ApiModelProperty("有效期类型: DAY(固定有效天数) TIME_PERIOD(固定时间段)")
        private CouponValidTypeEnum validType;

        @ApiModelProperty("有效天数")
        private Integer validDay;

        @ApiModelProperty("生效时间")
        private Long startTime;

        @ApiModelProperty("失效时间")
        private Long endTime;

        @ApiModelProperty("库存量")
        private Integer inventory;

        @ApiModelProperty("领取次数限制")
        private Integer quantityLimit;

        @ApiModelProperty("启禁状态")
        private Integer status;

        @ApiModelProperty("更新用户")
        private Long updatedBy;

        @ApiModelProperty("更新时间")
        private Long updateTime;

        @ApiModelProperty("创建用户")
        private Long createdBy;

        @ApiModelProperty("创建时间")
        @JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
        private Date createdTime;

        public static CouponQueryInfo from(String recv) {
            return JSON.parseObject(recv, CouponQueryInfo.class);
        }
    }

    /**
     * 新增或更新优惠券信息
     */
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class CouponInfo implements Serializable {

        @ApiModelProperty("优惠券ID")
        private Long id;

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

        @ApiModelProperty("描述")
        private String describe;

        @ApiModelProperty("客户端类型: TEACHER(老师端), STUDENT(学生端)")
        private ClientEnum clientType;

        @ApiModelProperty("可用品类: UNIVERSAL(全场通用) VIP(小酷Ai) PIANO(云酷琴房) MALL(商场购物券) MUSIC(单曲点播券) SPARRING(陪练课购买券) LIVE(直播课购买券) VIDEO(视频课购买券) ")
        private CouponCategoryEnum category;

        @ApiModelProperty("使用门槛")
        private BigDecimal useLimit;

        @ApiModelProperty("优惠金额")
        private BigDecimal discountPrice;

        @ApiModelProperty("优惠券类型: FULL_DISCOUNT(满减券) VOUCHER(代金券) ")
        private CouponTypeEnum couponType;

        @ApiModelProperty("有效期类型: DAY(固定有效天数) TIME_PERIOD(固定时间段)")
        private CouponValidTypeEnum validType;

        @ApiModelProperty("有效天数")
        private Integer validDay;

        @ApiModelProperty("生效时间")
        private Long startTime;

        @ApiModelProperty("失效时间")
        private Long endTime;

        @ApiModelProperty("库存量")
        private Integer inventory;

        @ApiModelProperty("领取次数限制")
        private Integer quantityLimit;

        @ApiModelProperty(value = "启禁状态, 0 停用 1 启用")
        private Integer status;

        @ApiModelProperty(value = "更新用户", hidden = true)
        private Long updatedBy;

        @ApiModelProperty(value = "更新时间", hidden = true)
        private Long updateTime;

        @ApiModelProperty(value = "创建用户", hidden = true)
        private Long createdBy;

        public String jsonString() {
            return JSON.toJSONString(this);
        }

        public boolean invalidRequestParam(Long userId) {

            if (Objects.isNull(getId())) {

                // 新增参数
                if (StringUtils.isEmpty(getName())) {
                    throw new BizException("优惠券名称不能为空");
                }

                if (Objects.isNull(getClientType())) {
                    throw new BizException("客户端不能为空");
                }

                if (Objects.isNull(getCategory())) {
                    throw new BizException("可用品类不能为空");
                }

                if (Objects.isNull(getCouponType())) {
                    throw new BizException("优惠券类型不能为空");
                }

                /*if (CouponTypeEnum.FULL_DISCOUNT == getCouponType()
                        && Optional.ofNullable(getUseLimit()).map(BigDecimal::intValue).orElse(0) <= 0) {
                    throw new BizException("满减金额未设置");
                }*/

                if (Objects.isNull(getValidType())) {
                    throw new BizException("有效期类型不能为空");
                }

                if (Optional.ofNullable(getValidDay()).orElse(0) <= 0
                        && (Optional.ofNullable(getStartTime()).orElse(0L) == 0
                            || Optional.ofNullable(getEndTime()).orElse(0L) == 0)) {
                    throw new BizException("优惠券时间有效期不合法");
                }

                this.createdBy(userId).initSaveParam();
            }
            // 更新用户参数
            this.updatedBy(userId).setUpdateTime(DateTime.now().getMillis());

            return false;
        }

        public CouponInfo initSaveParam() {

            return this.describe("")
                    .useLimit(BigDecimal.ZERO)
                    .discountPrice(BigDecimal.ZERO)
                    .validDay(0)
                    .startTime(0L)
                    .endTime(0L)
                    .inventory(0)
                    .quantityLimit(0)
                    .status(EStatus.DISABLE.getValue());
        }

        public CouponInfo describe(String describe) {
            if (StringUtils.isEmpty(this.describe)) {
                this.describe = describe;
            }
            return this;
        }

        public CouponInfo useLimit(BigDecimal useLimit) {
            if (Objects.isNull(this.useLimit)) {
                this.useLimit = useLimit;
            }
            return this;
        }

        public CouponInfo discountPrice(BigDecimal discountPrice) {
            if (Objects.isNull(this.discountPrice)) {
                this.discountPrice = discountPrice;
            }
            return this;
        }

        public CouponInfo validDay(Integer validDay) {
            if (Objects.isNull(this.validDay)) {
                this.validDay = validDay;
            }
            return this;
        }

        public CouponInfo startTime(Long startTime) {
            if (Objects.isNull(this.startTime)) {
                this.startTime = startTime;
            }
            return this;
        }

        public CouponInfo endTime(Long endTime) {
            if (Objects.isNull(this.endTime)) {
                this.endTime = endTime;
            }
            return this;
        }

        public CouponInfo inventory(Integer inventory) {
            if (Objects.isNull(this.inventory)) {
                this.inventory = inventory;
            }
            return this;
        }

        public CouponInfo quantityLimit(Integer quantityLimit) {
            if (Objects.isNull(this.quantityLimit)) {
                this.quantityLimit = quantityLimit;
            }
            return this;
        }

        public CouponInfo status(Integer status) {
            this.status = status;
            return this;
        }

        public CouponInfo createdBy(Long createdBy) {
            this.createdBy = createdBy;
            return this;
        }

        public CouponInfo updatedBy(Long updatedBy) {
            this.updatedBy = updatedBy;
            return this;
        }

    }
}
