package com.saas.admin.entity;

import com.saas.shared.annotation.TenantSchemaEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;

/**
 * Role entity for RBAC (Role-Based Access Control)
 * 
 * Roles group related permissions together.
 * Examples: "TENANT_ADMIN", "TENANT_VIEWER", "VOIP_MANAGER", "BILLING_ADMIN"
 * 
 * A user can have multiple roles, and each role can have multiple permissions.
 */
@Entity
@Table(name = "roles")
@TenantSchemaEntity("RBAC roles shared between admin and tenant databases")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Role {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    /**
     * Unique role name (e.g., "TENANT_ADMIN", "VOIP_MANAGER")
     * Used in business logic and permission checks
     */
    @Column(nullable = false, unique = true, length = 100)
    private String name;
    
    /**
     * Human-readable role description
     */
    @Column(length = 500)
    private String description;
    
    /**
     * Whether this role is active and can be assigned to users
     */
    @Column(nullable = false)
    @Builder.Default
    private Boolean isActive = true;
    
    /**
     * Whether this is a system role (cannot be deleted)
     * System roles: SYSTEM_ADMIN, TENANT_USER, etc.
     */
    @Column(nullable = false)
    @Builder.Default
    private Boolean isSystem = false;
    
    /**
     * Permissions associated with this role
     * Many-to-many relationship via role_permissions junction table
     */
    @OneToMany(mappedBy = "role", cascade = CascadeType.ALL, orphanRemoval = true)
    @Builder.Default
    private Set<RolePermission> rolePermissions = new HashSet<>();
    
    /**
     * Users who have this role
     * Many-to-many relationship via user_roles junction table
     */
    @OneToMany(mappedBy = "role", cascade = CascadeType.ALL, orphanRemoval = true)
    @Builder.Default
    private Set<UserRole> userRoles = new HashSet<>();
    
    @CreationTimestamp
    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    @Column(nullable = false)
    private LocalDateTime updatedAt;
    
    /**
     * Helper method to add permission to this role
     */
    public void addPermission(Permission permission) {
        RolePermission rolePermission = RolePermission.builder()
                .role(this)
                .permission(permission)
                .build();
        rolePermissions.add(rolePermission);
    }
    
    /**
     * Helper method to remove permission from this role
     */
    public void removePermission(Permission permission) {
        rolePermissions.removeIf(rp -> rp.getPermission().equals(permission));
    }
}
