"""Unit tests — Spec 027 RBAC matrix."""

from __future__ import annotations

import importlib.util
import sys
import unittest
from pathlib import Path

API_ROOT = Path(__file__).resolve().parents[1]


def _load(name: str, rel_path: str):
    path = API_ROOT / rel_path
    spec = importlib.util.spec_from_file_location(name, path)
    if spec is None or spec.loader is None:
        raise ImportError(path)
    mod = importlib.util.module_from_spec(spec)
    sys.modules[name] = mod
    spec.loader.exec_module(mod)
    return mod


permissions = _load("permissions_027", "app/permissions.py")
registry = _load("registry_027", "app/modules/registry.py")

ASSIGNABLE_ROLES = permissions.ASSIGNABLE_ROLES
HUMAN_ROLES = permissions.HUMAN_ROLES
can_create_foss_order = permissions.can_create_foss_order
can_manage_billing = permissions.can_manage_billing
can_read_billing = permissions.can_read_billing
can_read_crm_leads = permissions.can_read_crm_leads
can_validate_billing = permissions.can_validate_billing
is_assignable_role = permissions.is_assignable_role
ROLE_MODULE_DEFAULTS = registry.ROLE_MODULE_DEFAULTS
role_module_defaults = registry.role_module_defaults


class TestSpec027Permissions(unittest.TestCase):
    def test_human_role_count(self):
        self.assertGreaterEqual(len(HUMAN_ROLES), 13)

    def test_assignable_excludes_super_admin(self):
        self.assertNotIn("super_admin", ASSIGNABLE_ROLES)
        self.assertIn("sales_admin", ASSIGNABLE_ROLES)
        self.assertIn("sales_support", ASSIGNABLE_ROLES)

    def test_sales_admin_billing_validate(self):
        self.assertTrue(can_validate_billing("sales_admin"))
        self.assertTrue(can_manage_billing("sales_admin"))
        self.assertTrue(can_read_billing("sales_admin"))

    def test_sales_support_no_billing_validate(self):
        self.assertFalse(can_validate_billing("sales_support"))
        self.assertFalse(can_manage_billing("sales_support"))
        self.assertTrue(can_read_billing("sales_support"))

    def test_finance_billing(self):
        self.assertTrue(can_validate_billing("finance"))
        self.assertTrue(can_create_foss_order("finance"))

    def test_sales_roles_crm(self):
        self.assertTrue(can_read_crm_leads("sales_admin"))
        self.assertTrue(can_read_crm_leads("sales_support"))
        self.assertTrue(can_read_crm_leads("marketing"))

    def test_registration_roles(self):
        for role in (
            "ops_lead",
            "technician",
            "noc",
            "sales_admin",
            "sales_support",
            "finance",
            "marketing",
            "seo",
            "developer",
            "devops",
            "security_analyst",
            "content_editor",
            "agentic_operator",
        ):
            self.assertTrue(is_assignable_role(role), role)

    def test_role_module_defaults(self):
        sales_admin_mods = role_module_defaults("sales_admin")
        self.assertIsNotNone(sales_admin_mods)
        assert sales_admin_mods is not None
        self.assertIn("billing-recurrence", sales_admin_mods)
        self.assertNotIn("billing-recurrence", role_module_defaults("sales_support") or set())

    def test_ops_roles_no_module_filter(self):
        self.assertIsNone(role_module_defaults("ops_lead"))
        self.assertIsNone(role_module_defaults("technician"))

    def test_all_defaults_registered(self):
        for role, mods in ROLE_MODULE_DEFAULTS.items():
            self.assertIn("core", mods, role)


if __name__ == "__main__":
    unittest.main()
