/* (C) 2022 YiRing, Inc. */
package com.yiring.auth.domain.role;

import static com.yiring.auth.domain.role.Role.TABLE_NAME;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yiring.auth.domain.permission.Permission;
import com.yiring.auth.domain.user.User;
import com.yiring.common.domain.BasicEntity;
import jakarta.persistence.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import lombok.*;
import lombok.experimental.FieldDefaults;
import lombok.experimental.FieldNameConstants;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;
import org.hibernate.proxy.HibernateProxy;

/**
 * 角色
 *
 * @author ifzm
 * 2018/9/3 15:45
 */

@Getter
@Setter
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SQLDelete(sql = Permission.DELETE_SQL + BasicEntity.Where.WHERE_ID)
//@SQLDeleteAll(sql = Permission.DELETE_SQL)
@SQLRestriction(BasicEntity.Where.EXIST)
@Entity
@Table(
    name = TABLE_NAME,
    indexes = @Index(columnList = BasicEntity.Fields.deleted),
    uniqueConstraints = { @UniqueConstraint(columnNames = { Role.Fields.uid, BasicEntity.Fields.deleted }) }
)
@Comment("系统角色")
public class Role extends BasicEntity implements Serializable {

    public static final String TABLE_NAME = "SYS_ROLE";
    public static final String DELETE_SQL = "update " + TABLE_NAME + BasicEntity.Where.DELETE_SET;

    @Serial
    private static final long serialVersionUID = 910404402503275957L;

    @Comment("标识")
    @Column(nullable = false)
    String uid;

    @Comment("名称")
    @Column(nullable = false)
    String name;

    @Comment("是否禁用")
    @Column(columnDefinition = "bool default false", nullable = false)
    Boolean disabled;

    @JsonIgnore
    @Builder.Default
    @Comment("权限集合")
    @ManyToMany
    @ToString.Exclude
    Set<Permission> permissions = new HashSet<>();

    @JsonIgnore
    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @Builder.Default
    @Comment("用户集合")
    @ManyToMany
    @JoinTable(
        name = "SYS_USER_ROLES",
        joinColumns = { @JoinColumn(name = "role_id") },
        inverseJoinColumns = { @JoinColumn(name = "user_id") }
    )
    Set<User> users = new HashSet<>();

    @Override
    public final boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null) {
            return false;
        }
        Class<?> oEffectiveClass = o instanceof HibernateProxy
            ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass()
            : o.getClass();
        Class<?> thisEffectiveClass = this instanceof HibernateProxy
            ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass()
            : this.getClass();
        if (thisEffectiveClass != oEffectiveClass) {
            return false;
        }
        Role role = (Role) o;
        return getId() != null && Objects.equals(getId(), role.getId());
    }

    @Override
    public final int hashCode() {
        return this instanceof HibernateProxy
            ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode()
            : getClass().hashCode();
    }
}
