import os
import unittest
from types import SimpleNamespace


os.environ.setdefault("JWT_SECRET", "test-jwt-secret-value-with-32-chars")

from app.core.models import UserRole
from app.core.security import (
    get_allowed_routes,
    get_effective_permissions,
    has_permission,
)


class SecurityPermissionsTests(unittest.TestCase):
    def test_admin_deny_override_can_remove_specific_permission(self):
        user = SimpleNamespace(
            role=UserRole.admin,
            allowed_permissions_json=None,
            denied_permissions_json=["settings.write"],
            allowed_routes_json=None,
        )

        permissions = get_effective_permissions(user)

        self.assertIn("*", permissions)
        self.assertTrue(has_permission(user, "customers.write"))
        self.assertFalse(has_permission(user, "settings.write"))

    def test_viewer_gets_read_only_permissions(self):
        user = SimpleNamespace(
            role=UserRole.viewer,
            allowed_permissions_json=None,
            denied_permissions_json=None,
            allowed_routes_json=None,
        )

        permissions = get_effective_permissions(user)

        self.assertIn("customers.read", permissions)
        self.assertNotIn("customers.write", permissions)
        self.assertEqual([], get_allowed_routes(user))
        self.assertFalse(has_permission(user, "customers.write"))

    def test_user_overrides_add_and_remove_permissions(self):
        user = SimpleNamespace(
            role=UserRole.staff,
            allowed_permissions_json=["settings.read"],
            denied_permissions_json=["expenses.write"],
            allowed_routes_json=["Dashboard", "Customers"],
        )

        permissions = get_effective_permissions(user)

        self.assertIn("settings.read", permissions)
        self.assertNotIn("expenses.write", permissions)
        self.assertEqual(["Dashboard", "Customers"], get_allowed_routes(user))
        self.assertTrue(has_permission(user, "customers.read"))

    def test_helpers_normalize_empty_override_lists(self):
        user = SimpleNamespace(
            role=UserRole.staff,
            allowed_permissions_json=[],
            denied_permissions_json=[],
            allowed_routes_json=[],
        )

        permissions = get_effective_permissions(user)

        self.assertIn("customers.write", permissions)
        self.assertEqual([], get_allowed_routes(user))

    def test_malformed_string_overrides_are_ignored(self):
        user = SimpleNamespace(
            role=UserRole.staff,
            allowed_permissions_json="settings.read",
            denied_permissions_json="customers.read",
            allowed_routes_json="Dashboard",
        )

        permissions = get_effective_permissions(user)

        self.assertIn("customers.read", permissions)
        self.assertNotIn("g", permissions)
        self.assertNotIn("n", permissions)
        self.assertEqual([], get_allowed_routes(user))


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