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.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.AssetSource;
import com.izouma.nineth.enums.AssetStatus;
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 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(indexes = {
        @Index(columnList = "userId"),
        @Index(columnList = "tokenId"),
        @Index(columnList = "collectionId"),
        @Index(columnList = "minterId"),
        @Index(columnList = "ownerId"),
})
@DynamicUpdate
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ApiModel("资产")
public class Asset extends CollectionBaseEntity {

    public interface View {
        interface Basic {
        }

        interface Detail {
        }
    }

    @ApiModelProperty("用户ID")
    private Long userId;

    @ApiModelProperty("藏品ID")
    private Long collectionId;

    @ApiModelProperty("订单ID")
    private Long orderId;

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

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

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

    @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 String category;

    @ApiModelProperty("是否可转售")
    private boolean canResale;

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

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

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

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

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

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

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

    @ApiModelProperty("持有者头像")
    private String ownerAvatar;

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

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

    @ApiModelProperty("tokenId")
    private String tokenId;

    @ApiModelProperty("tokenId")
    private String chainTokenId;

    @ApiModelProperty("购买hash")
    private String txHash;

    @ApiModelProperty("消耗gas")
    private BigInteger gasUsed;

    @ApiModelProperty("区块高度")
    private BigInteger blockNumber;

    @ApiModelProperty("ipfs地址")
    private String ipfsUrl;

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

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

    @ApiModelProperty("转让hash")
    private String outTxHash;

    @ApiModelProperty("转让订单ID")
    private Long outOrderId;

    @ApiModelProperty("状态")
    @Enumerated(EnumType.STRING)
    private AssetStatus status;

    @ApiModelProperty("是否公开展示")
    private boolean publicShow;

    @ApiModelProperty("是否寄售")
    private boolean consignment;

    private Long publicCollectionId;

    private int likes;

    private Long fromAssetId;

    //地块ID
    private Long oasisId;

    private Long raceId;

    private Long groupId;

    private Long itemId;

    @ApiModelProperty("类型")
    @Enumerated(EnumType.STRING)
    private CollectionType type;

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

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

//    @ApiModelProperty("vip权利")
//    private Boolean vip;

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

    //    @Transient
    @Column(columnDefinition = "tinyint unsigned default 1")
    private boolean opened = true;

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

    private String hcTxHash;

    private BigInteger hcBlockNumber;

    private BigInteger hcGasUsed;

    private String hcTokenId;

    @Column(columnDefinition = "bit(1) default 0")
    private boolean safeFlag;

    private String prefixName;

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

    private LocalDateTime lockAt;

    private LocalDateTime lockTo;

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

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

    public static Asset create(Collection collection, User user) {
        return Asset.builder()
                .userId(user.getId())
                .collectionId(collection.getId())
                .minter(collection.getMinter())
                .minterId(collection.getMinterId())
                .minterAvatar(collection.getMinterAvatar())
                .name(collection.getName())
                .detail(collection.getDetail())
                .pic(collection.getPic())
                .model3d(collection.getModel3d())
                .properties(collection.getProperties())
                .privileges(collection.getPrivileges())
                .category(collection.getCategory())
                .canResale(collection.isCanResale())
                .royalties(collection.getRoyalties())
                .serviceCharge(collection.getServiceCharge())
                .price(collection.getPrice())
                .status(AssetStatus.NORMAL)
                .owner(user.getNickname())
                .ownerId(user.getId())
                .ownerAvatar(user.getAvatar())
                .type(collection.getType())
                .holdDays(collection.getHoldDays())
                .oldHoldDays(collection.getHoldDays())
                .source(AssetSource.OFFICIAL)
                .tags(new HashSet<>(collection.getTags()))
                .prefixName(collection.getPrefixName())
                .empower(collection.getEmpower())
                .companyId(collection.getCompanyId())
                .chainFlag(collection.getChainFlag())
                .build();
    }

    public static Asset create(BlindBoxItem item, User user, Integer holdDays) {
        return Asset.builder()
                .userId(user.getId())
                .collectionId(item.getCollectionId())
                .minter(item.getMinter())
                .minterId(item.getMinterId())
                .minterAvatar(item.getMinterAvatar())
                .name(item.getName())
                .detail(item.getDetail())
                .pic(item.getPic())
                .model3d(item.getModel3d())
                .properties(item.getProperties())
                .privileges(item.getPrivileges())
                .category(item.getCategory())
                .canResale(item.isCanResale())
                .royalties(item.getRoyalties())
                .serviceCharge(item.getServiceCharge())
                .price(item.getPrice())
                .status(AssetStatus.NORMAL)
                .owner(user.getNickname())
                .ownerId(user.getId())
                .ownerAvatar(user.getAvatar())
                .type(CollectionType.BLIND_BOX)
                .holdDays(holdDays)
                .oldHoldDays(holdDays)
                .source(AssetSource.OFFICIAL)
                .opened(false)
                .companyId(item.getCollection().getCompanyId())
                .chainFlag(item.getCollection().getChainFlag())
                .build();
    }
}
