/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: CartGoods
 * @Package cn.freemud.entities.vo
 * @Description:
 * @author: song.cai
 * @date: 2018/12/28 16:45
 * @version V1.0
 * @Copyright: 2018 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */

package cn.freemud.entities.vo;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CommonsConstant;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.util.Comparator;
import java.util.List;
import java.util.UUID;

@Data
public class CartGoods {
    /**
     * 购物车一行的Id（后台生成）
     */
    private String cartGoodsUid = UUID.randomUUID().toString();

    /**
     * 原有商品类型
     *
     * 溯源: 订单有自己的商品逻辑 无法使用原有字段类型记录处理
     * 该字段,保持和商品服务的商品类型一致
     */
    private Integer originalProductType;

    /**
     * 买一赠一时，存赠送主商品的cartGoodsUid用于标记是哪个商品赠送的
     */
    private String originalGoodsUid;

    /**
     * 加车时间
     */
    private Long addCartTime;

    /**
     * 单规格spuId,多规格skuId
     */
    private String goodsId;

    /**
     * 购买人的的姓名
     */
    private String userName;

    /**
     * 购买人的的userId
     */
    private String userId;

    /**
     * 购买人的的openId
     */
    private String openId;

    /**
     * 购买人的的头像
     */
    private String photoUrl;

    /**
     * 1.正常商品，2.商品券，3.套餐商品,4、换购券
     */
    private Integer goodsType;
    /**
     * 1:称重菜 或 套餐商品包含称重菜
     */
    private boolean weightType;
    /**
     * 重量
     */
    private Double weight;
    /**
     * 单位
     */
    private String unit;
    /**
     * 商品券code
     */
    private String couponCode;

    /**
     * 0 可用 1 不可用 （结算页识别是否需要传买M赠N券code）
     */
    @JsonIgnore
    private Integer canUseCoupon = 1;
    /**
     * 商品券名称
     */
    private String couponName;
    /**
     * 商品券门槛金额
     */
    private Long couponThresholdAmount;

    /**
     * 活动号
     */
    private String activityCode;

    private String spuId;
    private String skuId;
    /**
     * 所有属性attributeId的拼接
     */
    private String specProductId;
    /**
     * 购物车一行商品的原单价
     */
    private Long originalPrice;
    /**
     * 购物车一行商品的原单价总金额
     */
    private Long originalAmount;
    //购物车一行小料商品的原总价
    private Long originalMaterialAmount;
    /**
     * 购物车一行商品的包装费
     */
    private Long packPrice;

    /**
     * 购物车一行商品的现总价
     */
    private Long amount;
    /**
     * 购物车一行商品的现单价
     */
    private Long finalPrice;

    /**
     * 促销积分支付活动
     */
    private Long score;
    /**
     * 购物车商品券商品价格
     */
    private Long couponProductPrice;
    /**
     * 小料总金额
     */
    private Long materialAmount;
    /**
     * 购物车一行商品的数量
     */
    private Integer qty;

    /**
     * 参与活动商品数量 前端展示参数
     */
    private Integer activityNumber;
    /**
     * 购物车一行商品的名称
     */
    private String name;

    /**
     * 购物车一行商品英文名称
     */
    private String foreignName;

    /**
     * 商品的spuName
     */
    private String spuName;
    /**
     * 商品的spuForeignName
     */
    private String spuForeignName;

    /**
     * 商品的skuName
     */
    private String skuName;
    /**
     * skuForeignName
     */
    private String skuForeignName;

    /**
     * 购物车一行商品的副名称
     */
    private String subName;

    /**
     * 购物车一行商品的英文副名称
     */
    private String subForeignName;
    /**
     * 商品图片URL
     */
    private String pic;
    /**
     * 配料或属性
     */
    private List<CartGoodsExtra> extra;

    /**
     * 麦咖啡定制属性
     */
    private List<SpecialExtra> specialExtra;
    /**
     * 是否赠品
     */
    private Boolean isSendGoods;

    /**
     * 创建时间（mili）
     */
    private long createTimeMili = System.currentTimeMillis();
    /**
     * 1.5.5版本添加
     * 商品参与活动类型(61:买一赠一)
     */
    private Integer activityType;
    /**
     * 1.6.0 版本增加  节点ID
     */
    private String nodeId;
    /**
     * 1.6.0 版本增加 分类名
     */
    private String categoryName;

    /**
     * 统计分类编号
     */
    private String classificationId;
    /**
     * 统计分类名称
     */
    private String classificationName;

    private String classificationForeignName;
    /**
     * 是否限制库存
     * 用于创建订单时，是否扣减库存
     */
    private boolean isStockLimit;
    /**
     * 是否餐具商品
     */
    private Boolean isTableware = false;
    /**
     * 是否是月享卡商品
     */
    private int isMonthCard = 0;
    /**
     * 是否是买3赠1券商品
     */
    private int isB3S1Coupon = 0;
    /**
     * 是否使用了买3赠1券
     */
    private int isB3S1CouponGoods = 0;
    /**
     * 是否是太阳蛋商品
     */
    private int isSunnyCoupon=0;
    /**
     * 是否为可以使用买月享卡的商品 1:是；0:否
     */
    private int isMonthCardGoods = 0;
    /**
     * 月享卡信息
     */
    private MonthCardVo monthCardInfo;
    /**
     * 买3赠1券信息
     */
    private B3S1CouponGoodsInfoVo b3S1CouponGoodsInfo;
    /**
     * 第三方商品编码
     */
    private String customerCode;
    /**
     * 商品起售份数
     * 无起售份数默认值1
     */
    private Integer riseSell;
    /**
     * 折扣比例
     * 例如8折为80
     */
    private Integer memberDiscount;

    /**
     * 当前选择的优惠券优惠
     *
     */
    private Integer currentCouponDiscount;


    /**
     * 费率
     */
    private Double tax;

    /**
     * 费率代码
     */
    private String taxId;

    /**
     * 当前用户的会员等级(目前只有会员价活动使用)
     */
    private String currentMemberLevel;

    /**
     * 套餐固定商品
     */
    private List<ComboxGoods> productComboList;
    /**
     * 套餐可选商品
     */
    private List<ComboxGoods> productGroupList;

    /**
     * 商品原始加料数据
     */
    private List<MaterialGoods> productMaterialList;

    @Data
    public final static class CartGoodsExtra {
        /**
         * 属性Id
         */
        private String attributeId;
        /**
         * 属性名
         */
        private String attributeName;

        private String attributeForeignName;
    }

    @Data
    public final static class SpecialExtra {
        /**
         * 属性Id
         */
        private String attributeId;
        /**
         * 属性名
         */
        private String attributeName;
        private String attributeForeignName;


        /**
         * 麦咖啡特定属性入机code
         */
        private String specialCode;
    }

    @Data
    public final static class ComboxGoods {
        /**
         * 单规格spuId,多规格skuId
         */
        private String goodsId;
        private String spuId;
        private String skuId;
        private String skuName;
        private String skuForeignName;
        /**
         * 原有商品类型
         *
         * 溯源: 订单有自己的商品逻辑 无法使用原有字段类型记录处理
         * 该字段,保持和商品服务的商品类型一致
         */
        private Integer originalProductType;

        /**
         * 所有属性attributeId的拼接
         */
        private String specProductId;
        /**
         * 购物车一行商品的原单机
         */
        private Long originalPrice;
        /**
         * 购物车一行商品的现售单价
         */
        private Long finalPrice;

        /**
         * 购物车一行商品的包装费
         */
        private Long packPrice;

        /**
         * 购物车一行商品的原价
         */
        private Long originalAmount;

        /**
         * 购物车一行商品的现价
         */
        private Long amount;
        /**
         * 当前选择的优惠券优惠
         *
         */
        private Integer currentCouponDiscount;

        /**
         * 购物车一行商品的数量
         */
        private Integer qty;
        /**
         * 购物车一行商品的名称
         */
        private String name;

        private String foreignName;

        /**
         * 商品的spuName
         */
        private String spuName;
        private String spuForeignName;
        /**
         * 购物车一行商品的副名称
         */
        private String subName;
        private String subForeignName;
        /**
         * 商品图片URL
         */
        private String pic;
        /**
         * 配料或属性
         */
        private List<CartGoodsExtra> extra;

        /**
         * 麦咖啡特定属性
         */
        private List<SpecialExtra> specialExtra;
        /**
         * 1:称重菜
         */
        private boolean weightType;
        /**
         * 重量
         */
        private Double weight;
        /**
         * 单位
         */
        private String unit;
        /**
         * 第三方商品编号
         */
        private String customerCode;
        /**
         * 商品组Id
         */
        private Long productGroupId;

        /**
         * 费率
         */
        private Double tax;

        /**
         * 费率代码
         */
        private String taxId;

        /**
         * 加料商品商品价格
         */
        private Long materialAmount;
        /**
         * 商品原始加料数据
         */
        private List<MaterialGoods> productMaterialList;

        @Override
        public int hashCode() {
            StringBuilder sb = new StringBuilder();
            sb.append(goodsId);
            if (CollectionUtils.isNotEmpty(extra)) {
                extra.stream().sorted(Comparator.comparing(CartGoodsExtra::getAttributeId)).forEach(e -> sb.append(e.getAttributeId()));
            }
            return sb.toString().hashCode();
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(goodsId);
            if (CollectionUtils.isNotEmpty(extra)) {
                extra.stream().sorted(Comparator.comparing(CartGoodsExtra::getAttributeId)).forEach(e -> sb.append(e.getAttributeId()));
            }
            if (CollectionUtils.isNotEmpty(specialExtra)) {
                specialExtra.stream().sorted(Comparator.comparing(SpecialExtra::getAttributeId)).forEach(e -> sb.append(e.getAttributeId()));
            }
            return sb.toString();
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        // 原始字符串
        StringBuilder originalString = new StringBuilder();
        if (StringUtils.isNotBlank(goodsId) && goodsId.startsWith(CommonsConstant.COUPON_PREFIX)){
            originalString.append(spuId+skuId);
        } else {
            originalString.append(goodsId);
        }
        originalString.append(couponCode);

        if(StringUtils.isNotEmpty(userId)){
            originalString.append(userId);
        }

        if (CollectionUtils.isNotEmpty(extra)) {
            extra.stream().sorted(Comparator.comparing(CartGoodsExtra::getAttributeId)).forEach(e -> originalString.append(e.getAttributeId()));
        }
        if (CollectionUtils.isNotEmpty(productComboList)) {
            for (ComboxGoods goods : productComboList) {
                originalString.append(goods.toString());
                if (CollectionUtils.isNotEmpty(goods.getSpecialExtra())) {
                    goods.getSpecialExtra().stream().sorted(Comparator.comparing(SpecialExtra::getAttributeId)).forEach(e -> originalString.append(e.getAttributeId()));
                }
                if (CollectionUtils.isNotEmpty(goods.getProductMaterialList())) {
                    goods.getProductMaterialList().stream().sorted(Comparator.comparing(MaterialGoods::getSpuId)).forEach(e -> originalString.append(e.getSpuId()));
                }
            }
        }
        if (CollectionUtils.isNotEmpty(productGroupList)) {
            for (ComboxGoods goods : productGroupList) {
                originalString.append(goods.toString());
                if (CollectionUtils.isNotEmpty(goods.getProductMaterialList())) {
                    goods.getProductMaterialList().stream().sorted(Comparator.comparing(MaterialGoods::getSpuId)).forEach(e -> originalString.append(e.getSpuId()));
                }
            }
        }
        if (CollectionUtils.isNotEmpty(productMaterialList)) {
            // 小料的数量也要比较
            productMaterialList.stream().sorted(Comparator.comparing(MaterialGoods::getSpuId)).forEach(e -> {originalString.append(e.getSpuId());originalString.append(e.getQty());});
        }
        if (CollectionUtils.isNotEmpty(specialExtra)) {
            specialExtra.stream().sorted(Comparator.comparing(SpecialExtra::getAttributeId)).forEach(e -> originalString.append(e.getAttributeId()));
        }
        //当前字符串
        CartGoods cartGoods = (CartGoods) o;

        StringBuilder currentString = new StringBuilder();

        if (StringUtils.isNotBlank(cartGoods.getGoodsId()) && cartGoods.getGoodsId().startsWith(CommonsConstant.COUPON_PREFIX)){
            currentString.append(cartGoods.getSpuId()+cartGoods.getSkuId());
        } else {
            currentString.append(cartGoods.getGoodsId());
        }
        currentString.append(cartGoods.getCouponCode());

        if(StringUtils.isNotEmpty(cartGoods.getUserId())){
            currentString.append(cartGoods.getUserId());
        }

        if (CollectionUtils.isNotEmpty(cartGoods.getExtra())) {
            cartGoods.getExtra().stream().sorted(Comparator.comparing(CartGoodsExtra::getAttributeId)).forEach(e -> currentString.append(e.getAttributeId()));
        }
        if (CollectionUtils.isNotEmpty(cartGoods.getProductComboList())) {
            for (ComboxGoods goods : cartGoods.getProductComboList()) {
                currentString.append(goods.toString());
                if (CollectionUtils.isNotEmpty(goods.getSpecialExtra())) {
                    goods.getSpecialExtra().stream().sorted(Comparator.comparing(SpecialExtra::getAttributeId)).forEach(e -> currentString.append(e.getAttributeId()));
                }
                if (CollectionUtils.isNotEmpty(goods.getProductMaterialList())) {
                    goods.getProductMaterialList().stream().sorted(Comparator.comparing(MaterialGoods::getSpuId)).forEach(e -> currentString.append(e.getSpuId()));
                }
            }
        }
        if (CollectionUtils.isNotEmpty(cartGoods.getProductGroupList())) {
            for (ComboxGoods goods : cartGoods.getProductGroupList()) {
                currentString.append(goods.toString());
            }
        }
        if (CollectionUtils.isNotEmpty(cartGoods.getProductMaterialList())) {
            cartGoods.getProductMaterialList().stream().sorted(Comparator.comparing(MaterialGoods::getSpuId)).forEach(e -> {currentString.append(e.getSpuId());currentString.append(e.getQty());});
        }
        if (CollectionUtils.isNotEmpty(cartGoods.getSpecialExtra())) {
            cartGoods.getSpecialExtra().stream().sorted(Comparator.comparing(SpecialExtra::getAttributeId)).forEach(e -> currentString.append(e.getAttributeId()));
        }
        return StringUtils.equals(originalString.toString(), currentString.toString());
    }

    @Override
    public int hashCode() {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isNotBlank(goodsId) && goodsId.startsWith(CommonsConstant.COUPON_PREFIX)){
            sb.append(spuId+skuId);
        } else {
            sb.append(goodsId);
        }
        if (CollectionUtils.isNotEmpty(extra)) {
            extra.stream().sorted(Comparator.comparing(CartGoodsExtra::getAttributeId)).forEach(e -> sb.append(e.getAttributeId()));
        }
        int hashCode = sb.toString().hashCode();
        if (CollectionUtils.isNotEmpty(productComboList)) {
            for (ComboxGoods goods : productComboList) {
                hashCode += goods.hashCode();
            }
        }
        if (CollectionUtils.isNotEmpty(productGroupList)) {
            for (ComboxGoods goods : productGroupList) {
                hashCode += goods.hashCode();
            }
        }
        return hashCode;
    }

    /**
     * 是否为称重菜或套餐中存在称重菜
     * @return
     */
    public boolean hasWeight(){
        boolean hashWeight = this.isWeightType();
        if (!org.springframework.util.CollectionUtils.isEmpty(this.getProductComboList())) {
            long count = this.getProductComboList().stream().filter(CartGoods.ComboxGoods::isWeightType).count();
            hashWeight = hashWeight || count > 0;
        }
        if (!org.springframework.util.CollectionUtils.isEmpty(this.getProductGroupList())) {
            long count = this.getProductGroupList().stream().filter(CartGoods.ComboxGoods::isWeightType).count();
            hashWeight = hashWeight || count > 0;
        }
        return hashWeight;
    }

    @Data
    @NoArgsConstructor
    public static class MaterialGoods {

        /**
         * 加料Id
         */
        private String spuId;
        /**
         * 加料组id(对应入机键位)
         */
        private String groupId;
        /**
         * 加料名称
         */
        private String spuName;
        private String spuForeignName;

        /**
         * 购物车一行商品的原单价
         */
        private Long originalPrice;
        /**
         * 购物车一行商品的原价*数量
         */
        private Long originalAmount;
        /**
         * 购物车一行商品的现售单价
         */
        private Long finalPrice;
        /**
         * 购物车一行商品的现价*数量
         */
        private Long amount;

        /**
         * 当前选择的优惠券优惠
         *
         */
        private Integer currentCouponDiscount;


        /**
         * 麦咖啡入机键位
         */
        private String customerCode;

        /**
         * 数量
         */
        private Integer qty;

        /**
         * 原有商品类型
         *
         * 溯源: 订单有自己的商品逻辑 无法使用原有字段类型记录处理
         * 该字段,保持和商品服务的商品类型一致
         */
        private Integer originalProductType;
    }
}
