from __future__ import annotations

from django.contrib.auth.models import Group

from core.permissions import ROLE_CAPABILITIES, Role, normalize_role

from .models import GroupCapability


ROLE_GROUP_PREFIX = "role:"
SYSTEM_ROLES = (
    Role.SUPER_ADMIN,
    Role.STORE_MANAGER,
    Role.STOREKEEPER,
    Role.ACCOUNTANT,
    Role.SALES_OFFICER,
    Role.AUDITOR,
)


def role_group_name(role: str) -> str:
    return f"{ROLE_GROUP_PREFIX}{normalize_role(role)}"


def ensure_role_groups() -> dict[str, Group]:
    """
    Ensure one managed Django group per system role with mapped capabilities.
    """

    groups = {}
    for role in SYSTEM_ROLES:
        group, _ = Group.objects.get_or_create(name=role_group_name(role))
        groups[role] = group

        target_caps = ROLE_CAPABILITIES.get(role, set())
        existing_caps = set(
            GroupCapability.objects.filter(group=group).values_list("capability", flat=True)
        )

        to_add = target_caps - existing_caps
        to_remove = existing_caps - target_caps

        if to_add:
            GroupCapability.objects.bulk_create(
                [GroupCapability(group=group, capability=cap) for cap in sorted(to_add)],
                ignore_conflicts=True,
            )
        if to_remove:
            GroupCapability.objects.filter(group=group, capability__in=to_remove).delete()

    return groups


def sync_user_role_group(user) -> None:
    """
    Keep user in exactly one managed role group that matches their effective role.
    """

    groups = ensure_role_groups()
    effective_role = normalize_role(user.role)
    target_group = groups.get(effective_role)

    role_group_ids = list(
        Group.objects.filter(name__startswith=ROLE_GROUP_PREFIX).values_list("id", flat=True)
    )
    if role_group_ids:
        user.groups.remove(*role_group_ids)
    if target_group:
        user.groups.add(target_group)
