package com.izouma.nineth.domain;

import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.izouma.nineth.annotations.Searchable;
import com.izouma.nineth.annotations.SearchableOne;
import com.izouma.nineth.converter.FileObjectConverter;
import com.izouma.nineth.converter.FileObjectListConverter;
import com.izouma.nineth.converter.PrivilegeListConverter;
import com.izouma.nineth.converter.PropertyListConverter;
import com.izouma.nineth.enums.CollectionSource;
import com.izouma.nineth.enums.CollectionType;
import com.izouma.nineth.utils.CollectionTagSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Formula;

import javax.persistence.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Data
@Entity
@Table(name = "collection_info", indexes = {
        @Index(columnList = "type"),
        @Index(columnList = "source"),
        @Index(columnList = "minterId"),
        @Index(columnList = "onShelf"),
        @Index(columnList = "ownerId"),
        @Index(columnList = "assetId"),
        @Index(columnList = "salable"),
        @Index(columnList = "del"),
        @Index(columnList = "name"),
        @Index(columnList = "createdAt"),
        @Index(columnList = "sale"),
        @Index(columnList = "sort"),
        @Index(columnList = "del"),
        @Index(columnList = "price"),
        @Index(columnList = "likes"),
        @Index(columnList = "onShelf,del"),
        @Index(columnList = "onShelf,del,source"),
        @Index(columnList = "onShelf,del,source,salable"),
        @Index(columnList = "onShelf,del,source,salable,price"),
        @Index(columnList = "prefixName"),
})
@DynamicUpdate
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ApiModel("藏品")
public class Collection extends CollectionBaseEntity {

    public interface View {
        interface Basic {
        }

        interface Detail {
        }
    }

    @Transient
    private boolean liked;

    @Transient
    private boolean appointment;

    @Transient
    private int vipSurplus;

    @ApiModelProperty("名称")
    @Searchable
    private String name;

    @ApiModelProperty("图片")
    @Column(columnDefinition = "TEXT")
    @Convert(converter = FileObjectListConverter.class)
    private List<FileObject> pic;

    @Column(columnDefinition = "TEXT")
    @Convert(converter = FileObjectConverter.class)
    private FileObject model3d;

    @ApiModelProperty("铸造者")
    @SearchableOne
    private String minter;

    @ApiModelProperty("铸造者ID")
    private Long minterId;

    @ApiModelProperty("铸造者头像")
    private String minterAvatar;

    @ApiModelProperty("持有者")
    @SearchableOne
    private String owner;

    @ApiModelProperty("持有者者ID")
    private Long ownerId;

    private Long oasisId;

    private Long raceId;

    private Long groupId;

    private Long itemId;

    @ApiModelProperty("铸造者头像")
    private String ownerAvatar;

    @ApiModelProperty("详情")
    @Column(columnDefinition = "TEXT")
    private String detail;

    @ApiModelProperty("类型")
    @Enumerated(EnumType.STRING)
    @Column(length = 20)
    private CollectionType type;

    @Column(columnDefinition = "TEXT")
    @Convert(converter = PropertyListConverter.class)
    @ApiModelProperty("特性")
    private List<CollectionProperty> properties;

    @Column(columnDefinition = "TEXT")
    @Convert(converter = PrivilegeListConverter.class)
    @ApiModelProperty("特权")
    private List<Privilege> privileges;

    @ApiModelProperty("编号")
    private Integer number;

    @ApiModelProperty("是否可转售")
    @Column(columnDefinition = "tinyint unsigned")
    private boolean canResale;

    @ApiModelProperty("版税比例")
    private double royalties;

    @ApiModelProperty("手续费比例")
    private double serviceCharge;

    @ApiModelProperty("分类")
    private String category;

    @ApiModelProperty("来源")
    @Enumerated(EnumType.STRING)
    @Column(length = 20)
    private CollectionSource source;

    @ApiModelProperty("已售")
    private int sale;

    @ApiModelProperty("库存")
    private int stock;

    @ApiModelProperty("发行数量")
    private int total;

    @ApiModelProperty("点赞")
    private int likes;

    @ApiModelProperty("上架")
    @Column(columnDefinition = "tinyint unsigned")
    private boolean onShelf;

    @ApiModelProperty("可售")
    @Column(columnDefinition = "tinyint unsigned")
    private boolean salable;

    @ApiModelProperty("价格")
    @Column(precision = 10, scale = 2)
    private BigDecimal price;

    @ApiModelProperty("盲盒开售时间")
    private LocalDateTime startTime;

    @Column(columnDefinition = "tinyint unsigned")
    private boolean scheduleSale;

    private int sort;

    private Long assetId;

    private BigDecimal originalPrice;

    private Integer currentNumber;

    @Formula(value = "if(stock <= 0, 1, 0)")
    private int soldOut;

    @ApiModelProperty("限购数量")
    private int maxCount;

    @ApiModelProperty("限购识别码")
    private String countId;

    @Column(columnDefinition = "tinyint unsigned")
    private boolean scanCode;

    /*
    true: 没售罄
    false: 已售罄
     */
    @ApiModelProperty("手动售罄")
    @Column(columnDefinition = "tinyint unsigned")
    private boolean noSoldOut;

    @ApiModelProperty("拉新任务指标")
    private int assignment;

    @ApiModelProperty("优惠券支付")
    @Column(columnDefinition = "tinyint unsigned")
    private boolean couponPayment;

    @ApiModelProperty("分享背景")
    private String shareBg;

    @ApiModelProperty("注册背景")
    private String registerBg;

    @ApiModelProperty("总额度")
    private Integer totalQuota;

    @ApiModelProperty("剩余额度")
    private Integer vipQuota;

    @ApiModelProperty("延迟销售")
    private Boolean timeDelay;

    @ApiModelProperty("销售时间")
    private LocalDateTime saleTime;

    @ApiModelProperty("持有几天")
    private Integer holdDays;

    @ApiModelProperty("开启抢白名单")
    private Boolean openQuota;

    @ApiModelProperty("最低消费")
    private BigDecimal minimumCharge;

    @ApiModelProperty("是否支付中")
    private boolean inPaying;

    @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE})
    @JoinTable(
            name = "collection_tag",
            joinColumns = {@JoinColumn(name = "collection_id", referencedColumnName = "id",
                    foreignKey = @ForeignKey(foreignKeyDefinition =
                            "FOREIGN KEY (collection_id) REFERENCES collection_info(id) ON DELETE CASCADE ON UPDATE CASCADE"
                    ))},
            inverseJoinColumns = {@JoinColumn(name = "tag_id", referencedColumnName = "id",
                    foreignKey = @ForeignKey(foreignKeyDefinition =
                            "FOREIGN KEY (tag_id) REFERENCES tag(id) ON DELETE CASCADE ON UPDATE CASCADE"
                    ))})
    @JsonSerialize(using = CollectionTagSerializer.class, as = HashSet.class)
    @JsonView(View.Detail.class)
    private Set<Tag> tags = new HashSet<>();

    @ApiModelProperty("活动规则")
    @Column(columnDefinition = "TEXT")
    private String rule;

    private String     hcTxHash;
    private BigInteger hcBlockNumber;
    private BigInteger hcGasUsed;
    private String     hcTokenId;

    @ApiModelProperty("系列名称")
    @Column(length = 100)
    private String prefixName;

    @ApiModelProperty("赋能列表")
    @Column(columnDefinition = "TEXT")
    private String empower;

    @Column(columnDefinition = "bigint default 1 not null")
    private Long companyId = 1L;

    @ApiModelProperty("bit 0: 蚂蚁链, bit 1: 华储链")
    @Column(columnDefinition = "int default 3 not null")
    private int chainFlag;
}
