# #region Test.Auth.Repository [C:3] [TYPE Module] [SEMANTICS test,auth,repository,sqlalchemy]
# @BRIEF Tests for core/auth/repository.py — AuthRepository CRUD methods.
# @RELATION BINDS_TO -> [AuthRepositoryModule]
# @TEST_EDGE: user_not_found -> returns None
# @TEST_EDGE: empty_ad_groups -> returns []

from pathlib import Path
import sys

sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))

import os

os.environ.setdefault("AUTH_SECRET_KEY", "test-secret-key-for-testing")
os.environ.setdefault("JWT_AUDIENCE", "test-audience")
os.environ.setdefault("JWT_ISSUER", "test-issuer")

import pytest
from sqlalchemy import create_engine, event
from sqlalchemy.orm import Session


@pytest.fixture(scope="module")
def engine():
    eng = create_engine("sqlite:///:memory:", connect_args={"check_same_thread": False})
    event.listen(eng, "connect", lambda c, _: c.execute("PRAGMA foreign_keys=ON"))
    from src.models.mapping import Base
    Base.metadata.create_all(bind=eng)
    return eng


@pytest.fixture
def db(engine):
    session = Session(bind=engine)
    yield session
    session.rollback()
    # Clean up all tables after each test
    for table in reversed(list(Base.metadata.sorted_tables)):
        session.execute(table.delete())
    session.commit()
    session.close()


# Import Base here for cleanup fixture
from src.models.mapping import Base


@pytest.fixture
def repo(db):
    from src.core.auth.repository import AuthRepository
    return AuthRepository(db)


@pytest.fixture
def seed_data(db):
    """Seed test data into the database."""
    from src.models.auth import User, Role, Permission, ADGroupMapping
    from src.models.profile import UserDashboardPreference

    user = User(id="user-1", username="testuser", email="test@example.com", full_name="Test User")
    db.add(user)

    role = Role(id="role-1", name="admin", description="Administrator")
    db.add(role)

    perm = Permission(id="perm-1", resource="plugin:backup", action="EXECUTE")
    db.add(perm)

    # Create mapping
    mapping = ADGroupMapping(id="mapping-1", ad_group="AD-Admin", role_id="role-1")
    db.add(mapping)

    pref = UserDashboardPreference(user_id="user-1", show_only_my_dashboards=True)
    db.add(pref)

    db.commit()
    return {"user": user, "role": role, "perm": perm, "pref": pref}


class TestGetUserById:
    def test_found(self, repo, seed_data):
        result = repo.get_user_by_id("user-1")
        assert result is not None
        assert result.id == "user-1"
        assert result.username == "testuser"

    def test_not_found(self, repo):
        result = repo.get_user_by_id("nonexistent")
        assert result is None


class TestGetUserByUsername:
    def test_found(self, repo, seed_data):
        result = repo.get_user_by_username("testuser")
        assert result is not None
        assert result.id == "user-1"

    def test_not_found(self, repo):
        result = repo.get_user_by_username("unknown")
        assert result is None


class TestGetRoleById:
    def test_found(self, repo, seed_data):
        result = repo.get_role_by_id("role-1")
        assert result is not None
        assert result.name == "admin"

    def test_not_found(self, repo):
        result = repo.get_role_by_id("nonexistent")
        assert result is None


class TestGetRoleByName:
    def test_found(self, repo, seed_data):
        result = repo.get_role_by_name("admin")
        assert result is not None
        assert result.id == "role-1"

    def test_not_found(self, repo):
        result = repo.get_role_by_name("unknown")
        assert result is None


class TestGetPermissionById:
    def test_found(self, repo, seed_data):
        result = repo.get_permission_by_id("perm-1")
        assert result is not None
        assert result.resource == "plugin:backup"

    def test_not_found(self, repo):
        result = repo.get_permission_by_id("nonexistent")
        assert result is None


class TestGetPermissionByResourceAction:
    def test_found(self, repo, seed_data):
        result = repo.get_permission_by_resource_action("plugin:backup", "EXECUTE")
        assert result is not None
        assert result.id == "perm-1"

    def test_not_found(self, repo):
        result = repo.get_permission_by_resource_action("unknown", "READ")
        assert result is None


class TestListPermissions:
    def test_returns_all(self, repo, seed_data):
        results = repo.list_permissions()
        assert len(results) == 1
        assert results[0].id == "perm-1"

    def test_empty(self, repo):
        results = repo.list_permissions()
        assert results == []


class TestGetUserDashboardPreference:
    def test_found(self, repo, seed_data):
        result = repo.get_user_dashboard_preference("user-1")
        assert result is not None
        assert result.user_id == "user-1"

    def test_not_found(self, repo):
        result = repo.get_user_dashboard_preference("nonexistent")
        assert result is None


class TestGetRolesByAdGroups:
    def test_empty_groups_returns_empty(self, repo):
        result = repo.get_roles_by_ad_groups([])
        assert result == []

    def test_found(self, repo, seed_data):
        result = repo.get_roles_by_ad_groups(["AD-Admin"])
        assert len(result) == 1
        assert result[0].id == "role-1"

    def test_no_match_returns_empty(self, repo):
        result = repo.get_roles_by_ad_groups(["AD-Nonexistent"])
        assert result == []

    def test_multiple_groups(self, repo, seed_data):
        from src.models.auth import ADGroupMapping, Role

        # Add another mapping
        role2 = Role(id="role-2", name="viewer")
        repo.db.add(role2)
        repo.db.add(ADGroupMapping(id="mapping-2", ad_group="AD-Viewer", role_id="role-2"))
        repo.db.commit()

        result = repo.get_roles_by_ad_groups(["AD-Admin", "AD-Viewer"])
        assert len(result) == 2
# #endregion Test.Auth.Repository
