#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
RBAC Example and Testing Script

This script demonstrates how to use the Role-Based Access Control (RBAC) system
in the Identitas authentication library.
"""

from Identitas.provider.api.init import init
from Identitas.provider.api.auth import register, login
from Identitas.provider.api.rbac import (
    # Role management
    create_role, delete_role, get_role, list_roles, update_role,
    # Right management
    create_right, delete_right, get_right, list_rights, list_rights_by_resource, update_right,
    # User-Role assignment
    assign_role_to_user, remove_role_from_user, get_user_roles, get_users_with_role,
    # Role-Right assignment
    assign_right_to_role, remove_right_from_role, get_role_rights, get_roles_with_right,
    # Permission checking
    user_has_right, user_has_resource_action, get_user_all_rights, get_user_permissions_summary
)
import os

# Initialize database
debug_mode = os.getenv("DEBUG", "false").lower() == "true"
engine = init("data/rbac_test.db", debug=debug_mode)

print("=" * 80)
print("IDENTITAS RBAC SYSTEM - DEMONSTRATION")
print("=" * 80)

# ============================================================
# 1) CREATE USERS
# ============================================================
print("\n[1] Creating users...")
token_admin = register(engine, "admin_user", "AdminPass123!@", "admin@example.com")
token_editor = register(engine, "editor_user", "EditorPass123!@", "editor@example.com")
token_viewer = register(engine, "viewer_user", "ViewerPass123!@", "viewer@example.com")
print(f"✅ Created 3 users: admin_user, editor_user, viewer_user")

# Extract user IDs from tokens (for demonstration, using hardcoded IDs from first registrations)
admin_id = 1
editor_id = 2
viewer_id = 3

# ============================================================
# 2) CREATE ROLES
# ============================================================
print("\n[2] Creating roles...")
admin_role = create_role(engine, "Administrator", "Full system access")
editor_role = create_role(engine, "Editor", "Can create and edit content")
viewer_role = create_role(engine, "Viewer", "Can only view content")
print(f"✅ Created 3 roles: Administrator, Editor, Viewer")

# ============================================================
# 3) CREATE RIGHTS
# ============================================================
print("\n[3] Creating rights...")

# User management rights
create_right(engine, "create_user", "user", "create", "Can create new users")
create_right(engine, "read_user", "user", "read", "Can view user information")
create_right(engine, "update_user", "user", "update", "Can modify user information")
create_right(engine, "delete_user", "user", "delete", "Can delete users")

# Content management rights
create_right(engine, "create_content", "content", "create", "Can create new content")
create_right(engine, "read_content", "content", "read", "Can view content")
create_right(engine, "update_content", "content", "update", "Can modify content")
create_right(engine, "delete_content", "content", "delete", "Can delete content")

# Report rights
create_right(engine, "view_reports", "report", "read", "Can view reports")
create_right(engine, "create_reports", "report", "create", "Can create reports")

# Settings rights
create_right(engine, "manage_settings", "settings", "admin", "Can manage system settings")

print(f"✅ Created 10 rights across 4 resources (user, content, report, settings)")

# ============================================================
# 4) ASSIGN RIGHTS TO ROLES
# ============================================================
print("\n[4] Assigning rights to roles...")

# Administrator role: all rights
rights = list_rights(engine)
for right in rights:
    assign_right_to_role(engine, admin_role.id, right.id)
print(f"   ✅ Administrator role: All {len(rights)} rights assigned")

# Editor role: content and report rights (no user management, no settings)
editor_rights = [
    "create_content", "read_content", "update_content",
    "read_user",  # Can view users but not modify
    "view_reports", "create_reports"
]
for right_name in editor_rights:
    right = get_right_by_name(engine, right_name)
    if right:
        assign_right_to_role(engine, editor_role.id, right.id)
print(f"   ✅ Editor role: 6 rights assigned")

# Viewer role: read-only access
viewer_rights = ["read_content", "read_user", "view_reports"]
for right_name in viewer_rights:
    right = get_right_by_name(engine, right_name)
    if right:
        assign_right_to_role(engine, viewer_role.id, right.id)
print(f"   ✅ Viewer role: 3 rights assigned")


def get_right_by_name(engine, name: str):
    """Helper function to get right by name"""
    for right in list_rights(engine):
        if right.name == name:
            return right
    return None


# ============================================================
# 5) ASSIGN ROLES TO USERS
# ============================================================
print("\n[5] Assigning roles to users...")
assign_role_to_user(engine, admin_id, admin_role.id)
print(f"   ✅ admin_user assigned to Administrator role")

assign_role_to_user(engine, editor_id, editor_role.id)
print(f"   ✅ editor_user assigned to Editor role")

assign_role_to_user(engine, viewer_id, viewer_role.id)
print(f"   ✅ viewer_user assigned to Viewer role")

# ============================================================
# 6) CHECK PERMISSIONS
# ============================================================
print("\n[6] Checking permissions...")

def check_permission(user_id, username, resource, action):
    has_perm = user_has_resource_action(engine, user_id, resource, action)
    status = "✅ YES" if has_perm else "❌ NO"
    print(f"   {status}: {username} can {action} {resource}")
    return has_perm


print("\n   Admin User Permissions:")
check_permission(admin_id, "admin_user", "user", "delete")
check_permission(admin_id, "admin_user", "settings", "admin")
check_permission(admin_id, "admin_user", "content", "create")

print("\n   Editor User Permissions:")
check_permission(editor_id, "editor_user", "content", "create")
check_permission(editor_id, "editor_user", "content", "update")
check_permission(editor_id, "editor_user", "user", "delete")
check_permission(editor_id, "editor_user", "settings", "admin")

print("\n   Viewer User Permissions:")
check_permission(viewer_id, "viewer_user", "content", "read")
check_permission(viewer_id, "viewer_user", "content", "create")
check_permission(viewer_id, "viewer_user", "user", "update")

# ============================================================
# 7) GET USER PERMISSIONS SUMMARY
# ============================================================
print("\n[7] User Permissions Summary:")

print("\n   Admin User:")
admin_perms = get_user_permissions_summary(engine, admin_id)
for resource, actions in admin_perms.items():
    print(f"      {resource}: {', '.join(actions)}")

print("\n   Editor User:")
editor_perms = get_user_permissions_summary(engine, editor_id)
for resource, actions in editor_perms.items():
    print(f"      {resource}: {', '.join(actions)}")

print("\n   Viewer User:")
viewer_perms = get_user_permissions_summary(engine, viewer_id)
for resource, actions in viewer_perms.items():
    print(f"      {resource}: {', '.join(actions)}")

# ============================================================
# 8) LIST INFORMATION
# ============================================================
print("\n[8] Listing Information:")

print("\n   All Roles:")
for role in list_roles(engine):
    print(f"      - {role.name}: {role.description}")

print("\n   All Rights (grouped by resource):")
resources = {}
for right in list_rights(engine):
    if right.resource not in resources:
        resources[right.resource] = []
    resources[right.resource].append((right.name, right.action))

for resource, right_list in sorted(resources.items()):
    print(f"      {resource}:")
    for name, action in right_list:
        print(f"         - {name} ({action})")

print("\n   Admin User Roles:")
for role in get_user_roles(engine, admin_id):
    print(f"      - {role.name}")

print("\n   Users with Administrator Role:")
for user in get_users_with_role(engine, admin_role.id):
    print(f"      - {user.username}")

# ============================================================
# 9) MODIFY PERMISSIONS
# ============================================================
print("\n[9] Modifying permissions...")

# Add another role to editor
assign_role_to_user(engine, editor_id, viewer_role.id)
print(f"   ✅ Added Viewer role to editor_user (now has both Editor and Viewer roles)")

# Verify editor now has viewer permissions too
has_view_perm = user_has_resource_action(engine, editor_id, "report", "read")
print(f"   ✅ Verified: editor_user can now view reports (inherited from Viewer role)")

# Remove a right from a role
viewer_rights_list = get_role_rights(engine, viewer_role.id)
if viewer_rights_list:
    # Find read_user right and remove it
    for right in viewer_rights_list:
        if right.name == "read_user":
            remove_right_from_role(engine, viewer_role.id, right.id)
            print(f"   ✅ Removed 'read_user' right from Viewer role")
            break

# ============================================================
# 10) DEMONSTRATE ROLE-BASED DECORATORS IN FLASK (Example)
# ============================================================
print("\n[10] Flask Decorator Examples (see code for implementation):")
print("""
   Example 1: Route with Session Required
   =========================================
   @app.route('/dashboard')
   @require_session
   def dashboard(user_id):
       return f"Hello User {user_id}!"
   
   Example 2: Route with Specific Right Required
   ==============================================
   @app.route('/admin/users', methods=['DELETE'])
   @require_right('delete_user')
   def delete_user_admin(user_id):
       # Only users with 'delete_user' right can access
       return "User deleted"
   
   Example 3: Route with Resource:Action Permission
   =================================================
   @app.route('/reports/create', methods=['POST'])
   @require_resource_action('report', 'create')
   def create_report(user_id):
       # Only users who can 'create' on 'report' resource can access
       return "Report created"
""")

print("\n" + "=" * 80)
print("RBAC DEMONSTRATION COMPLETE")
print("=" * 80)
