package com.social.media.domain.user.valueobjects;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Objects;

/**
 * Value object representing user role and permissions.
 * 
 * Defines what actions a user can perform within a company.
 * 
 * @author Social Media Manager Team
 * @since 2.0.0
 */
@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserRole {
    
    public enum RoleType {
        ADMIN("Administrator", "Full access to all company features"),
        MANAGER("Manager", "Can manage content and users"),
        EDITOR("Editor", "Can create and edit content"),
        VIEWER("Viewer", "Read-only access");
        
        private final String displayName;
        private final String description;
        
        RoleType(String displayName, String description) {
            this.displayName = displayName;
            this.description = description;
        }
        
        public String getDisplayName() { return displayName; }
        public String getDescription() { return description; }
    }
    
    @Column(name = "role_type", nullable = false, length = 20)
    private RoleType roleType;
    
    @Column(name = "can_manage_users", nullable = false)
    private Boolean canManageUsers = false;
    
    @Column(name = "can_manage_social_accounts", nullable = false)
    private Boolean canManageSocialAccounts = false;
    
    @Column(name = "can_create_posts", nullable = false)
    private Boolean canCreatePosts = false;
    
    @Column(name = "can_edit_posts", nullable = false)
    private Boolean canEditPosts = false;
    
    @Column(name = "can_publish_posts", nullable = false)
    private Boolean canPublishPosts = false;
    
    @Column(name = "can_delete_posts", nullable = false)
    private Boolean canDeletePosts = false;
    
    @Column(name = "can_view_analytics", nullable = false)
    private Boolean canViewAnalytics = false;
    
    @Column(name = "can_manage_company_settings", nullable = false)
    private Boolean canManageCompanySettings = false;
    
    private UserRole(RoleType roleType) {
        this.roleType = Objects.requireNonNull(roleType, "Role type cannot be null");
        setDefaultPermissions();
    }
    
    /**
     * Create a role with default permissions
     */
    public static UserRole of(RoleType roleType) {
        return new UserRole(roleType);
    }
    
    /**
     * Create a custom role with specific permissions
     */
    public static UserRole custom(RoleType baseRoleType, Boolean canManageUsers, Boolean canManageSocialAccounts,
                                 Boolean canCreatePosts, Boolean canEditPosts, Boolean canPublishPosts,
                                 Boolean canDeletePosts, Boolean canViewAnalytics, Boolean canManageCompanySettings) {
        UserRole role = new UserRole(baseRoleType);
        role.canManageUsers = canManageUsers != null ? canManageUsers : role.canManageUsers;
        role.canManageSocialAccounts = canManageSocialAccounts != null ? canManageSocialAccounts : role.canManageSocialAccounts;
        role.canCreatePosts = canCreatePosts != null ? canCreatePosts : role.canCreatePosts;
        role.canEditPosts = canEditPosts != null ? canEditPosts : role.canEditPosts;
        role.canPublishPosts = canPublishPosts != null ? canPublishPosts : role.canPublishPosts;
        role.canDeletePosts = canDeletePosts != null ? canDeletePosts : role.canDeletePosts;
        role.canViewAnalytics = canViewAnalytics != null ? canViewAnalytics : role.canViewAnalytics;
        role.canManageCompanySettings = canManageCompanySettings != null ? canManageCompanySettings : role.canManageCompanySettings;
        return role;
    }
    
    /**
     * Set default permissions based on role type
     */
    private void setDefaultPermissions() {
        switch (roleType) {
            case ADMIN:
                canManageUsers = true;
                canManageSocialAccounts = true;
                canCreatePosts = true;
                canEditPosts = true;
                canPublishPosts = true;
                canDeletePosts = true;
                canViewAnalytics = true;
                canManageCompanySettings = true;
                break;
            case MANAGER:
                canManageUsers = true;
                canManageSocialAccounts = true;
                canCreatePosts = true;
                canEditPosts = true;
                canPublishPosts = true;
                canDeletePosts = true;
                canViewAnalytics = true;
                canManageCompanySettings = false;
                break;
            case EDITOR:
                canManageUsers = false;
                canManageSocialAccounts = false;
                canCreatePosts = true;
                canEditPosts = true;
                canPublishPosts = true;
                canDeletePosts = false;
                canViewAnalytics = true;
                canManageCompanySettings = false;
                break;
            case VIEWER:
                canManageUsers = false;
                canManageSocialAccounts = false;
                canCreatePosts = false;
                canEditPosts = false;
                canPublishPosts = false;
                canDeletePosts = false;
                canViewAnalytics = true;
                canManageCompanySettings = false;
                break;
        }
    }
    
    /**
     * Check if role has any management permission
     */
    public boolean hasManagementPermissions() {
        return Boolean.TRUE.equals(canManageUsers) || 
               Boolean.TRUE.equals(canManageSocialAccounts) || 
               Boolean.TRUE.equals(canManageCompanySettings);
    }
    
    /**
     * Check if role has any content creation permission
     */
    public boolean hasContentPermissions() {
        return Boolean.TRUE.equals(canCreatePosts) || 
               Boolean.TRUE.equals(canEditPosts) || 
               Boolean.TRUE.equals(canPublishPosts);
    }
    
    /**
     * Check if role is admin level
     */
    public boolean isAdmin() {
        return roleType == RoleType.ADMIN;
    }
    
    /**
     * Check if role can perform specific action
     */
    public boolean canPerformAction(String action) {
        return switch (action.toLowerCase()) {
            case "manage_users" -> Boolean.TRUE.equals(canManageUsers);
            case "manage_social_accounts" -> Boolean.TRUE.equals(canManageSocialAccounts);
            case "create_posts" -> Boolean.TRUE.equals(canCreatePosts);
            case "edit_posts" -> Boolean.TRUE.equals(canEditPosts);
            case "publish_posts" -> Boolean.TRUE.equals(canPublishPosts);
            case "delete_posts" -> Boolean.TRUE.equals(canDeletePosts);
            case "view_analytics" -> Boolean.TRUE.equals(canViewAnalytics);
            case "manage_company_settings" -> Boolean.TRUE.equals(canManageCompanySettings);
            default -> false;
        };
    }
    
    /**
     * Create a copy with modified permissions
     */
    public UserRole withPermission(String permission, boolean allowed) {
        return switch (permission.toLowerCase()) {
            case "manage_users" -> UserRole.custom(roleType, allowed, canManageSocialAccounts, 
                canCreatePosts, canEditPosts, canPublishPosts, canDeletePosts, canViewAnalytics, canManageCompanySettings);
            case "manage_social_accounts" -> UserRole.custom(roleType, canManageUsers, allowed, 
                canCreatePosts, canEditPosts, canPublishPosts, canDeletePosts, canViewAnalytics, canManageCompanySettings);
            case "create_posts" -> UserRole.custom(roleType, canManageUsers, canManageSocialAccounts, 
                allowed, canEditPosts, canPublishPosts, canDeletePosts, canViewAnalytics, canManageCompanySettings);
            case "edit_posts" -> UserRole.custom(roleType, canManageUsers, canManageSocialAccounts, 
                canCreatePosts, allowed, canPublishPosts, canDeletePosts, canViewAnalytics, canManageCompanySettings);
            case "publish_posts" -> UserRole.custom(roleType, canManageUsers, canManageSocialAccounts, 
                canCreatePosts, canEditPosts, allowed, canDeletePosts, canViewAnalytics, canManageCompanySettings);
            case "delete_posts" -> UserRole.custom(roleType, canManageUsers, canManageSocialAccounts, 
                canCreatePosts, canEditPosts, canPublishPosts, allowed, canViewAnalytics, canManageCompanySettings);
            case "view_analytics" -> UserRole.custom(roleType, canManageUsers, canManageSocialAccounts, 
                canCreatePosts, canEditPosts, canPublishPosts, canDeletePosts, allowed, canManageCompanySettings);
            case "manage_company_settings" -> UserRole.custom(roleType, canManageUsers, canManageSocialAccounts, 
                canCreatePosts, canEditPosts, canPublishPosts, canDeletePosts, canViewAnalytics, allowed);
            default -> this;
        };
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        UserRole userRole = (UserRole) obj;
        return roleType == userRole.roleType &&
               Objects.equals(canManageUsers, userRole.canManageUsers) &&
               Objects.equals(canManageSocialAccounts, userRole.canManageSocialAccounts) &&
               Objects.equals(canCreatePosts, userRole.canCreatePosts) &&
               Objects.equals(canEditPosts, userRole.canEditPosts) &&
               Objects.equals(canPublishPosts, userRole.canPublishPosts) &&
               Objects.equals(canDeletePosts, userRole.canDeletePosts) &&
               Objects.equals(canViewAnalytics, userRole.canViewAnalytics) &&
               Objects.equals(canManageCompanySettings, userRole.canManageCompanySettings);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(roleType, canManageUsers, canManageSocialAccounts, canCreatePosts, 
            canEditPosts, canPublishPosts, canDeletePosts, canViewAnalytics, canManageCompanySettings);
    }
    
    @Override
    public String toString() {
        return roleType.getDisplayName();
    }
}
