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

from apps.accounts.permissions import (
    ROLE_ACCOUNTS,
    ROLE_EMPLOYEE,
    ROLE_HR_ADMIN,
    ROLE_IT,
    ROLE_MANAGER,
    ROLE_NAMES,
    ROLE_PAYROLL_OFFICER,
    ROLE_SUPER_ADMIN,
)

# Model permissions are deliberately conservative. Business actions are performed
# through company-scoped service/view workflows, not by granting broad Django
# model change/delete access to every role.
ROLE_APP_ACCESS = {
    ROLE_SUPER_ADMIN: {"*"},
    ROLE_HR_ADMIN: {"organization", "employees", "attendance", "leave", "workflow", "exits", "imports", "audit"},
    ROLE_PAYROLL_OFFICER: {"employees", "attendance", "leave", "payroll", "loans", "workflow", "audit"},
    ROLE_MANAGER: {"employees", "attendance", "leave", "workflow", "exits"},
    ROLE_EMPLOYEE: {"employees", "attendance", "leave", "workflow", "payroll"},
    ROLE_ACCOUNTS: {"payroll", "loans", "workflow", "exits", "audit"},
    ROLE_IT: {"attendance", "workflow", "exits"},
}

# Only HR Admin and Payroll Officer receive selected add/change model permissions.
# Delete permissions are reserved for Super Admin; financial/history rows should
# normally be status-driven, reversed or deactivated instead of deleted.
CHANGE_APPS_BY_ROLE = {
    ROLE_HR_ADMIN: {"organization", "employees", "attendance", "leave", "workflow", "exits", "imports"},
    ROLE_PAYROLL_OFFICER: {"payroll", "loans"},
}


class Command(BaseCommand):
    help = "Create standard HR & Payroll roles with least-privilege baseline model permissions."

    def handle(self, *args, **options):
        all_permissions = Permission.objects.select_related("content_type").all()
        by_app = {}
        for perm in all_permissions:
            by_app.setdefault(perm.content_type.app_label, []).append(perm)

        for role_name in ROLE_NAMES:
            group, _ = Group.objects.get_or_create(name=role_name)
            allowed_apps = ROLE_APP_ACCESS[role_name]
            if "*" in allowed_apps:
                selected = list(all_permissions)
            else:
                selected = []
                change_apps = CHANGE_APPS_BY_ROLE.get(role_name, set())
                for app_label in allowed_apps:
                    for perm in by_app.get(app_label, []):
                        if perm.codename.startswith("view_"):
                            selected.append(perm)
                        elif app_label in change_apps and (
                            perm.codename.startswith("add_") or perm.codename.startswith("change_")
                        ):
                            selected.append(perm)
            group.permissions.set(selected)
            self.stdout.write(self.style.SUCCESS(f"{role_name}: {len(selected)} least-privilege permissions"))
