"""
Management command to create default roles and groups for PX360.
"""

from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand

from apps.accounts.models import Role


class Command(BaseCommand):
    help = "Create default roles and groups for PX360 system"

    def handle(self, *args, **options):
        """Create default roles"""

        roles_config = [
            {
                "name": "px_admin",
                "display_name": "PX Admin",
                "description": "Full system access. Can manage all hospitals, departments, and configurations.",
                "level": 100,
            },
            {
                "name": "hospital_admin",
                "display_name": "Hospital Admin",
                "description": "Hospital-level access. Can manage their hospital and its departments.",
                "level": 80,
            },
            {
                "name": "department_manager",
                "display_name": "Department Manager",
                "description": "Department-level access. Can manage their department.",
                "level": 60,
            },
            {
                "name": "director",
                "display_name": "Director",
                "description": "Multi-department access. Can view data for departments where their direct reports (via report_to) work.",
                "level": 70,
            },
            {
                "name": "px_management",
                "display_name": "PX Management",
                "description": "Can manage PX actions, complaints, and surveys.",
                "level": 50,
            },
            {
                "name": "px_employee",
                "display_name": "PX Employee",
                "description": "Can work with complaints, inquiries, observations, appreciation, suggestions, QI projects, departments, staff surveys, physician dashboard, government tickets, communication requests, and reports. View-only access to references and standards.",
                "level": 40,
            },
            {
                "name": "staff",
                "display_name": "Staff",
                "description": "Basic staff access.",
                "level": 20,
            },
            {
                "name": "viewer",
                "display_name": "Viewer",
                "description": "Read-only access to reports and dashboards.",
                "level": 10,
            },
            {
                "name": "executive",
                "display_name": "Executive",
                "description": "C-Suite and top management. System-wide analytics, executive summaries, and predictive insights access.",
                "level": 90,
            },
            {
                "name": "px_source_user",
                "display_name": "PX Source User",
                "description": "External source users who can create complaints and inquiries from their assigned source. Limited access to their own created data only.",
                "level": 5,
            },
        ]

        created_count = 0
        updated_count = 0

        for role_data in roles_config:
            # Get or create group
            group, group_created = Group.objects.get_or_create(name=role_data["display_name"])

            if group_created:
                self.stdout.write(self.style.SUCCESS(f"Created group: {group.name}"))

            # Get or create role
            role, role_created = Role.objects.get_or_create(
                name=role_data["name"],
                defaults={
                    "display_name": role_data["display_name"],
                    "description": role_data["description"],
                    "group": group,
                    "level": role_data["level"],
                },
            )

            if role_created:
                created_count += 1
                self.stdout.write(self.style.SUCCESS(f"✓ Created role: {role.display_name} (level {role.level})"))
            else:
                # Update existing role
                role.display_name = role_data["display_name"]
                role.description = role_data["description"]
                role.level = role_data["level"]
                role.group = group
                role.save()
                updated_count += 1
                self.stdout.write(self.style.WARNING(f"↻ Updated role: {role.display_name}"))

            # Assign permissions based on role level
            self._assign_permissions(role, group)

        self.stdout.write(
            self.style.SUCCESS(f"\n✓ Roles setup complete: {created_count} created, {updated_count} updated")
        )
        self.stdout.write(self.style.SUCCESS(f"Total roles: {Role.objects.count()}"))

    def _assign_permissions(self, role, group):
        """
        Assign permissions to group based on role level.
        This is a basic implementation - expand as needed.
        """
        # Clear existing permissions
        group.permissions.clear()

        # Get all permissions
        all_permissions = Permission.objects.all()

        # PX Admin gets all permissions
        if role.name == "px_admin":
            group.permissions.set(all_permissions)
            return

        # Hospital Admin gets most permissions except user management
        if role.name == "hospital_admin":
            permissions = Permission.objects.exclude(
                content_type__app_label="auth", codename__in=["add_user", "delete_user", "change_user"]
            )
            group.permissions.set(permissions)
            return

        # Department Manager gets department-level permissions
        if role.name == "department_manager":
            # Add view permissions for most models
            view_permissions = Permission.objects.filter(codename__startswith="view_")
            group.permissions.set(view_permissions)
            return

        # Director gets view permissions (same as Department Manager)
        if role.name == "director":
            view_permissions = Permission.objects.filter(codename__startswith="view_")
            group.permissions.set(view_permissions)
            return

        # Department Respondent gets view + inquiry response permissions
        if role.name == "department_respondent":
            respondent_permissions = Permission.objects.filter(
                content_type__app_label__in=["complaints", "organizations", "observations"],
                codename__startswith="view_",
            )
            group.permissions.set(respondent_permissions)
            return

        # PX Employee gets complaint and action permissions
        if role.name == "px_employee":
            staff_permissions = Permission.objects.filter(
                content_type__app_label__in=["complaints", "px_action_center", "surveys"]
            )
            group.permissions.set(staff_permissions)
            return

        # Executive gets view permissions system-wide + executive_summary access
        if role.name == "executive":
            view_permissions = Permission.objects.filter(codename__startswith="view_")
            exec_perms = Permission.objects.filter(content_type__app_label="executive_summary")
            group.permissions.set(list(view_permissions) + list(exec_perms))
            return

        # PX Source User gets limited complaint/inquiry permissions
        if role.name == "px_source_user":
            source_user_perms = Permission.objects.filter(
                content_type__app_label__in=["complaints"],
                codename__in=[
                    "add_complaint",
                    "view_complaint",
                    "change_complaint",
                    "add_inquiry",
                    "view_inquiry",
                    "change_inquiry",
                ],
            )
            group.permissions.set(source_user_perms)
            return

        # Others get basic view permissions
        view_permissions = Permission.objects.filter(codename__startswith="view_")
        group.permissions.set(view_permissions)
