# tests/integration/api/v1/admin/test_admin_users.py
"""
Integration tests for admin user management API endpoints.

Tests the /api/v1/admin/admin-users/* endpoints.
"""

import pytest


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
class TestAdminUsersListAPI:
    """Test listing admin users."""

    def test_list_admin_users_as_super_admin(
        self, client, super_admin_headers, test_platform_admin
    ):
        """Test listing admin users as super admin."""
        response = client.get(
            "/api/v1/admin/admin-users",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert "admins" in data
        assert "total" in data
        assert data["total"] >= 1

    def test_list_admin_users_as_platform_admin_forbidden(
        self, client, platform_admin_headers
    ):
        """Test that platform admin cannot list admin users."""
        response = client.get(
            "/api/v1/admin/admin-users",
            headers=platform_admin_headers,
        )

        assert response.status_code == 403  # Super admin required

    def test_list_admin_users_excludes_super_admins(
        self, client, super_admin_headers, test_platform_admin
    ):
        """Test listing admin users excluding super admins."""
        response = client.get(
            "/api/v1/admin/admin-users",
            params={"include_super_admins": False},
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        # All returned admins should not be super admins
        for admin in data["admins"]:
            assert admin["role"] != "super_admin"


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
class TestAdminUsersCreateAPI:
    """Test creating platform admins."""

    def test_create_platform_admin_success(
        self, client, super_admin_headers, test_platform, another_platform
    ):
        """Test creating a new platform admin."""
        response = client.post(
            "/api/v1/admin/admin-users",
            json={
                "email": "new_platform_admin@example.com",
                "username": "new_platform_admin",
                "password": "securepass123",
                "first_name": "New",
                "last_name": "Admin",
                "platform_ids": [test_platform.id, another_platform.id],
            },
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["email"] == "new_platform_admin@example.com"
        assert data["username"] == "new_platform_admin"
        assert data["role"] == "platform_admin"
        assert len(data["platform_assignments"]) == 2

    def test_create_platform_admin_duplicate_email(
        self, client, super_admin_headers, test_platform, test_platform_admin
    ):
        """Test creating platform admin with duplicate email fails."""
        response = client.post(
            "/api/v1/admin/admin-users",
            json={
                "email": test_platform_admin.email,
                "username": "unique_username",
                "password": "securepass123",
                "platform_ids": [test_platform.id],
            },
            headers=super_admin_headers,
        )

        assert response.status_code == 409  # Conflict - user already exists

    def test_create_platform_admin_as_platform_admin_forbidden(
        self, client, platform_admin_headers, test_platform
    ):
        """Test that platform admin cannot create other admins."""
        response = client.post(
            "/api/v1/admin/admin-users",
            json={
                "email": "another@example.com",
                "username": "another",
                "password": "securepass123",
                "platform_ids": [test_platform.id],
            },
            headers=platform_admin_headers,
        )

        assert response.status_code == 403  # Forbidden for non-super admin


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
class TestAdminUsersPlatformAssignmentAPI:
    """Test admin platform assignment endpoints."""

    def test_assign_admin_to_platform(
        self, client, super_admin_headers, test_platform_admin, test_platform
    ):
        """Test assigning an admin to a platform."""
        response = client.post(
            f"/api/v1/admin/admin-users/{test_platform_admin.id}/platforms/{test_platform.id}",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert "message" in data
        assert data["user_id"] == test_platform_admin.id
        assert data["platform_id"] == test_platform.id

    def test_remove_admin_from_platform(
        self, client, super_admin_headers, db, test_platform_admin, test_platform, test_super_admin
    ):
        """Test removing an admin from a platform."""
        from app.modules.tenancy.models import AdminPlatform

        # First create an assignment
        assignment = AdminPlatform(
            user_id=test_platform_admin.id,
            platform_id=test_platform.id,
            is_active=True,
            assigned_by_user_id=test_super_admin.id,
        )
        db.add(assignment)
        db.commit()

        response = client.delete(
            f"/api/v1/admin/admin-users/{test_platform_admin.id}/platforms/{test_platform.id}",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert "message" in data

    def test_get_admin_platforms(
        self, client, super_admin_headers, db, test_platform_admin, test_platform, test_super_admin
    ):
        """Test getting platforms for an admin."""
        from app.modules.tenancy.models import AdminPlatform

        # Create assignment
        assignment = AdminPlatform(
            user_id=test_platform_admin.id,
            platform_id=test_platform.id,
            is_active=True,
            assigned_by_user_id=test_super_admin.id,
        )
        db.add(assignment)
        db.commit()

        response = client.get(
            f"/api/v1/admin/admin-users/{test_platform_admin.id}/platforms",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert "platforms" in data
        assert len(data["platforms"]) == 1
        assert data["platforms"][0]["id"] == test_platform.id


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
class TestAdminUsersSuperAdminToggleAPI:
    """Test super admin promotion/demotion."""

    def test_promote_to_super_admin(
        self, client, super_admin_headers, test_platform_admin
    ):
        """Test promoting a platform admin to super admin."""
        response = client.put(
            f"/api/v1/admin/admin-users/{test_platform_admin.id}/super-admin",
            json={"role": "super_admin"},
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["role"] == "super_admin"

    def test_demote_from_super_admin(
        self, client, super_admin_headers, db, auth_manager
    ):
        """Test demoting a super admin to platform admin."""
        from app.modules.tenancy.models import User

        # Create another super admin to demote
        another_super = User(
            email="demote_test@example.com",
            username="demote_test",
            hashed_password=auth_manager.hash_password("pass"),
            role="super_admin",
            is_active=True,
        )
        db.add(another_super)
        db.commit()

        response = client.put(
            f"/api/v1/admin/admin-users/{another_super.id}/super-admin",
            json={"role": "platform_admin"},
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["role"] == "platform_admin"


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
class TestAdminAuthPlatformSelectionAPI:
    """Test platform selection for platform admins."""

    def test_get_accessible_platforms_super_admin(
        self, client, super_admin_headers, test_platform
    ):
        """Test getting accessible platforms as super admin."""
        response = client.get(
            "/api/v1/admin/auth/accessible-platforms",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["is_super_admin"] is True
        assert "platforms" in data
        assert data["requires_platform_selection"] is False

    def test_get_accessible_platforms_platform_admin(
        self, client, db, test_platform_admin, test_platform, test_super_admin, auth_manager
    ):
        """Test getting accessible platforms as platform admin."""
        from app.modules.tenancy.models import AdminPlatform

        # Create assignment
        assignment = AdminPlatform(
            user_id=test_platform_admin.id,
            platform_id=test_platform.id,
            is_active=True,
            assigned_by_user_id=test_super_admin.id,
        )
        db.add(assignment)
        db.commit()

        # Login as platform admin
        response = client.post(
            "/api/v1/admin/auth/login",
            json={
                "email_or_username": test_platform_admin.username,
                "password": "platformadminpass123",
            },
        )
        assert response.status_code == 200
        token = response.json()["access_token"]

        # Get accessible platforms
        response = client.get(
            "/api/v1/admin/auth/accessible-platforms",
            headers={"Authorization": f"Bearer {token}"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["is_super_admin"] is False
        assert len(data["platforms"]) == 1
        assert data["platforms"][0]["id"] == test_platform.id
        assert data["requires_platform_selection"] is True

    def test_select_platform_success(
        self, client, db, test_platform_admin, test_platform, test_super_admin
    ):
        """Test selecting a platform as platform admin."""
        from app.modules.tenancy.models import AdminPlatform

        # Create assignment
        assignment = AdminPlatform(
            user_id=test_platform_admin.id,
            platform_id=test_platform.id,
            is_active=True,
            assigned_by_user_id=test_super_admin.id,
        )
        db.add(assignment)
        db.commit()

        # Login
        response = client.post(
            "/api/v1/admin/auth/login",
            json={
                "email_or_username": test_platform_admin.username,
                "password": "platformadminpass123",
            },
        )
        token = response.json()["access_token"]

        # Select platform
        response = client.post(
            "/api/v1/admin/auth/select-platform",
            params={"platform_id": test_platform.id},
            headers={"Authorization": f"Bearer {token}"},
        )

        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
        # New token should be different
        assert data["access_token"] != token

    def test_select_platform_not_assigned(
        self, client, db, test_platform_admin, test_platform
    ):
        """Test selecting a platform that admin is not assigned to."""
        # Login (no platform assignment exists)
        response = client.post(
            "/api/v1/admin/auth/login",
            json={
                "email_or_username": test_platform_admin.username,
                "password": "platformadminpass123",
            },
        )
        token = response.json()["access_token"]

        # Try to select platform
        response = client.post(
            "/api/v1/admin/auth/select-platform",
            params={"platform_id": test_platform.id},
            headers={"Authorization": f"Bearer {token}"},
        )

        assert response.status_code == 403  # Access denied

    def test_select_platform_as_super_admin_succeeds(
        self, client, super_admin_headers, test_platform
    ):
        """Test that super admin can select platform context."""
        response = client.post(
            "/api/v1/admin/auth/select-platform",
            params={"platform_id": test_platform.id},
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["platform_id"] == test_platform.id
        assert data["platform_code"] == test_platform.code
