"""Role permission helpers for ensuring and updating access matrix."""

from __future__ import annotations

from collections import defaultdict
from typing import Dict

from sqlalchemy import select
from sqlalchemy.orm import Session

from backend.constants.role_features import (
    ROLE_FEATURE_KEYS,
    get_default_permission,
)
from backend.constants.roles import ROLE_VALUES
from backend.db.models import RolePermission


def ensure_role_permissions_initialized(session: Session) -> None:
    """Seed permissions table once using default matrix if table is empty."""

    has_permissions = session.execute(select(RolePermission.id)).first()
    if has_permissions:
        return

    for role in ROLE_VALUES:
        for feature_key in ROLE_FEATURE_KEYS:
            permission = RolePermission(
                role=role,
                feature_key=feature_key,
                allowed=get_default_permission(role, feature_key),
            )
            session.add(permission)

    session.commit()


def fetch_role_permissions_map(session: Session) -> Dict[str, Dict[str, bool]]:
    """Return permissions map keyed by role then feature."""

    ensure_role_permissions_initialized(session)
    permissions = defaultdict(dict)
    results = session.execute(select(RolePermission)).scalars().all()
    for perm in results:
        permissions[perm.role][perm.feature_key] = bool(perm.allowed)
    return dict(permissions)


def set_role_permissions(session: Session, permissions: Dict[str, Dict[str, bool]]) -> None:
    """Update permissions based on provided map."""

    ensure_role_permissions_initialized(session)
    existing = {
        (perm.role, perm.feature_key): perm
        for perm in session.execute(select(RolePermission)).scalars().all()
    }

    updated = False
    for role, feature_map in permissions.items():
        for feature_key, allowed in feature_map.items():
            key = (role, feature_key)
            perm = existing.get(key)
            if perm is None:
                perm = RolePermission(role=role, feature_key=feature_key)
                session.add(perm)
                existing[key] = perm
            if perm.allowed != bool(allowed):
                perm.allowed = bool(allowed)
                updated = True

    if updated:
        session.commit()

