"""
Organization E2E workflow tests with real PostgreSQL.

These tests validate complete organization workflows including:
- Creating organizations (via admin)
- Viewing user's organizations
- Organization membership management
- Organization updates

Usage:
    make test-e2e          # Run all E2E tests
"""

from uuid import uuid4

import pytest

pytestmark = [
    pytest.mark.e2e,
    pytest.mark.postgres,
    pytest.mark.asyncio,
]


async def register_and_login(client, email: str, password: str = "SecurePassword123!"):  # noqa: S107
    """Helper to register a user and get tokens."""
    # Register
    await client.post(
        "/api/v1/auth/register",
        json={
            "email": email,
            "password": password,
            "first_name": "Test",
            "last_name": "User",
        },
    )

    # Login
    login_resp = await client.post(
        "/api/v1/auth/login",
        json={"email": email, "password": password},
    )
    tokens = login_resp.json()
    return tokens


async def create_superuser_and_login(client, db_session):
    """Helper to create a superuser directly in DB and login."""
    from app.crud.user import user as user_crud
    from app.schemas.users import UserCreate

    email = f"admin-{uuid4().hex[:8]}@example.com"
    password = "AdminPassword123!"

    # Create superuser directly
    user_in = UserCreate(
        email=email,
        password=password,
        first_name="Admin",
        last_name="User",
        is_superuser=True,
    )
    await user_crud.create(db_session, obj_in=user_in)

    # Login
    login_resp = await client.post(
        "/api/v1/auth/login",
        json={"email": email, "password": password},
    )
    return login_resp.json(), email


class TestOrganizationWorkflows:
    """Test organization management workflows."""

    async def test_user_has_no_organizations_initially(self, e2e_client):
        """New users should have no organizations."""
        email = f"e2e-{uuid4().hex[:8]}@example.com"
        tokens = await register_and_login(e2e_client, email)

        response = await e2e_client.get(
            "/api/v1/organizations/me",
            headers={"Authorization": f"Bearer {tokens['access_token']}"},
        )

        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        assert len(data) == 0

    async def test_get_organizations_requires_auth(self, e2e_client):
        """Organizations endpoint requires authentication."""
        response = await e2e_client.get("/api/v1/organizations/me")
        assert response.status_code == 401

    async def test_get_nonexistent_organization(self, e2e_client):
        """Getting a non-member organization returns 403."""
        email = f"e2e-{uuid4().hex[:8]}@example.com"
        tokens = await register_and_login(e2e_client, email)

        fake_org_id = str(uuid4())
        response = await e2e_client.get(
            f"/api/v1/organizations/{fake_org_id}",
            headers={"Authorization": f"Bearer {tokens['access_token']}"},
        )

        # Should be 403 (not a member) or 404 (not found)
        assert response.status_code in [403, 404]


class TestOrganizationMembershipWorkflows:
    """Test organization membership workflows."""

    async def test_non_member_cannot_view_org_details(self, e2e_client):
        """Users cannot view organizations they're not members of."""
        # Create two users
        user1_email = f"e2e-user1-{uuid4().hex[:8]}@example.com"
        user2_email = f"e2e-user2-{uuid4().hex[:8]}@example.com"

        await register_and_login(e2e_client, user1_email)
        user2_tokens = await register_and_login(e2e_client, user2_email)

        # User2 tries to access a random org ID
        fake_org_id = str(uuid4())
        response = await e2e_client.get(
            f"/api/v1/organizations/{fake_org_id}",
            headers={"Authorization": f"Bearer {user2_tokens['access_token']}"},
        )

        assert response.status_code in [403, 404]

    async def test_non_member_cannot_view_org_members(self, e2e_client):
        """Users cannot view members of organizations they don't belong to."""
        email = f"e2e-{uuid4().hex[:8]}@example.com"
        tokens = await register_and_login(e2e_client, email)

        fake_org_id = str(uuid4())
        response = await e2e_client.get(
            f"/api/v1/organizations/{fake_org_id}/members",
            headers={"Authorization": f"Bearer {tokens['access_token']}"},
        )

        assert response.status_code in [403, 404]

    async def test_non_admin_cannot_update_organization(self, e2e_client):
        """Regular users cannot update organizations (need admin role)."""
        email = f"e2e-{uuid4().hex[:8]}@example.com"
        tokens = await register_and_login(e2e_client, email)

        fake_org_id = str(uuid4())
        response = await e2e_client.put(
            f"/api/v1/organizations/{fake_org_id}",
            headers={"Authorization": f"Bearer {tokens['access_token']}"},
            json={"name": "Updated Name"},
        )

        assert response.status_code in [403, 404]


class TestOrganizationWithMembers:
    """Test organization workflows using e2e_org_with_members fixture."""

    async def test_owner_can_view_organization(self, e2e_client, e2e_org_with_members):
        """Organization owner can view organization details."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            f"/api/v1/organizations/{org['org_id']}",
            headers={
                "Authorization": f"Bearer {org['owner']['tokens']['access_token']}"
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["id"] == org["org_id"]
        assert data["name"] == org["org_name"]

    async def test_member_can_view_organization(self, e2e_client, e2e_org_with_members):
        """Organization member can view organization details."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            f"/api/v1/organizations/{org['org_id']}",
            headers={
                "Authorization": f"Bearer {org['member']['tokens']['access_token']}"
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["id"] == org["org_id"]

    async def test_owner_can_list_members(self, e2e_client, e2e_org_with_members):
        """Organization owner can list members."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            f"/api/v1/organizations/{org['org_id']}/members",
            headers={
                "Authorization": f"Bearer {org['owner']['tokens']['access_token']}"
            },
        )

        assert response.status_code == 200
        data = response.json()
        # Should have owner + member = at least 2 members
        assert len(data) >= 2

    async def test_member_can_list_members(self, e2e_client, e2e_org_with_members):
        """Organization member can list members."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            f"/api/v1/organizations/{org['org_id']}/members",
            headers={
                "Authorization": f"Bearer {org['member']['tokens']['access_token']}"
            },
        )

        assert response.status_code == 200

    async def test_owner_appears_in_my_organizations(
        self, e2e_client, e2e_org_with_members
    ):
        """Owner sees organization in their organizations list."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            "/api/v1/organizations/me",
            headers={
                "Authorization": f"Bearer {org['owner']['tokens']['access_token']}"
            },
        )

        assert response.status_code == 200
        data = response.json()
        org_ids = [o["id"] for o in data]
        assert org["org_id"] in org_ids

    async def test_member_appears_in_my_organizations(
        self, e2e_client, e2e_org_with_members
    ):
        """Member sees organization in their organizations list."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            "/api/v1/organizations/me",
            headers={
                "Authorization": f"Bearer {org['member']['tokens']['access_token']}"
            },
        )

        assert response.status_code == 200
        data = response.json()
        org_ids = [o["id"] for o in data]
        assert org["org_id"] in org_ids

    async def test_owner_can_update_organization(
        self, e2e_client, e2e_org_with_members
    ):
        """Organization owner can update organization details."""
        org = e2e_org_with_members
        new_description = f"Updated at {uuid4().hex[:8]}"

        response = await e2e_client.put(
            f"/api/v1/organizations/{org['org_id']}",
            headers={
                "Authorization": f"Bearer {org['owner']['tokens']['access_token']}"
            },
            json={"description": new_description},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["description"] == new_description

    async def test_member_cannot_update_organization(
        self, e2e_client, e2e_org_with_members
    ):
        """Regular member cannot update organization details."""
        org = e2e_org_with_members

        response = await e2e_client.put(
            f"/api/v1/organizations/{org['org_id']}",
            headers={
                "Authorization": f"Bearer {org['member']['tokens']['access_token']}"
            },
            json={"description": "Should fail"},
        )

        assert response.status_code == 403

    async def test_non_member_cannot_view_organization(
        self, e2e_client, e2e_org_with_members
    ):
        """Non-members cannot view organization details."""
        org = e2e_org_with_members

        # Create a new user who is not a member
        non_member_email = f"nonmember-{uuid4().hex[:8]}@example.com"
        tokens = await register_and_login(e2e_client, non_member_email)

        response = await e2e_client.get(
            f"/api/v1/organizations/{org['org_id']}",
            headers={"Authorization": f"Bearer {tokens['access_token']}"},
        )

        assert response.status_code == 403

    async def test_get_organization_by_slug(self, e2e_client, e2e_org_with_members):
        """Organization can be retrieved by slug."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            f"/api/v1/organizations/slug/{org['org_slug']}",
            headers={
                "Authorization": f"Bearer {org['owner']['tokens']['access_token']}"
            },
        )

        # May be 200 or 404/403 depending on implementation
        assert response.status_code in [200, 403, 404]


class TestOrganizationAdminOperations:
    """Test organization admin operations."""

    async def test_admin_list_org_members_with_pagination(
        self, e2e_client, e2e_superuser, e2e_org_with_members
    ):
        """Admin can list org members with pagination."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            f"/api/v1/admin/organizations/{org['org_id']}/members",
            headers={
                "Authorization": f"Bearer {e2e_superuser['tokens']['access_token']}"
            },
            params={"page": 1, "limit": 10},
        )

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

    async def test_admin_list_org_members_filter_active(
        self, e2e_client, e2e_superuser, e2e_org_with_members
    ):
        """Admin can filter org members by active status."""
        org = e2e_org_with_members
        response = await e2e_client.get(
            f"/api/v1/admin/organizations/{org['org_id']}/members",
            headers={
                "Authorization": f"Bearer {e2e_superuser['tokens']['access_token']}"
            },
            params={"is_active": True},
        )

        assert response.status_code == 200
