"""Integration tests for account management endpoints."""

import pytest
from httpx import AsyncClient


class TestAccountEndpoints:
    """Test suite for account management endpoints."""

    @pytest.mark.asyncio
    async def test_get_my_account(self, client: AsyncClient, auth_headers: dict):
        """Test getting current user's account."""
        response = await client.get("/api/v1/accounts/me", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert "id" in data
        assert "name" in data
        assert "display_code" in data
        assert "owner_id" in data
        assert len(data["display_code"]) == 8

    @pytest.mark.asyncio
    async def test_get_my_subscription(self, client: AsyncClient, auth_headers: dict):
        """Test getting current user's subscription details."""
        response = await client.get("/api/v1/accounts/me/subscription", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert "subscription" in data
        assert "limits" in data
        assert "usage" in data
        assert data["subscription"]["plan"] == "free"
        assert data["subscription"]["status"] == "active"
        assert data["limits"]["max_trees"] == 3
        assert data["limits"]["max_sessions_per_month"] == 20

    @pytest.mark.asyncio
    async def test_get_my_members(self, client: AsyncClient, auth_headers: dict):
        """Test getting members of current user's account."""
        response = await client.get("/api/v1/accounts/me/members", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        assert len(data) >= 1
        # Current user should be in members list
        assert any(m["account_role"] == "owner" for m in data)

    @pytest.mark.asyncio
    async def test_update_my_account(self, client: AsyncClient, auth_headers: dict):
        """Test updating account name."""
        response = await client.patch(
            "/api/v1/accounts/me",
            json={"name": "Updated Account Name"},
            headers=auth_headers
        )
        assert response.status_code == 200
        assert response.json()["name"] == "Updated Account Name"

    @pytest.mark.asyncio
    async def test_update_account_requires_owner(self, client: AsyncClient):
        """Test that non-owners cannot update account settings."""
        # Register two users
        owner_data = {
            "email": "owner@example.com",
            "password": "OwnerPass123!",
            "name": "Owner"
        }
        await client.post("/api/v1/auth/register", json=owner_data)

        # Login as owner and create an invite
        login_resp = await client.post("/api/v1/auth/login/json", json={
            "email": "owner@example.com",
            "password": "OwnerPass123!"
        })
        owner_headers = {"Authorization": f"Bearer {login_resp.json()['access_token']}"}

        # Create invite
        invite_resp = await client.post(
            "/api/v1/accounts/me/invites",
            json={"email": "member@example.com", "role": "engineer"},
            headers=owner_headers
        )
        assert invite_resp.status_code == 201
        invite_code = invite_resp.json()["code"]

        # Register member with account invite code
        member_data = {
            "email": "member@example.com",
            "password": "MemberPass123!",
            "name": "Member",
            "account_invite_code": invite_code
        }
        reg_resp = await client.post("/api/v1/auth/register", json=member_data)
        assert reg_resp.status_code == 201
        assert reg_resp.json()["account_role"] == "engineer"

        # Login as member
        member_login = await client.post("/api/v1/auth/login/json", json={
            "email": "member@example.com",
            "password": "MemberPass123!"
        })
        member_headers = {"Authorization": f"Bearer {member_login.json()['access_token']}"}

        # Member should not be able to update account
        response = await client.patch(
            "/api/v1/accounts/me",
            json={"name": "Hacked Name"},
            headers=member_headers
        )
        assert response.status_code == 403

    @pytest.mark.asyncio
    async def test_create_and_list_invites(self, client: AsyncClient, auth_headers: dict):
        """Test creating and listing account invites."""
        # Create invite
        response = await client.post(
            "/api/v1/accounts/me/invites",
            json={"email": "invitee@example.com", "role": "engineer"},
            headers=auth_headers
        )
        assert response.status_code == 201
        data = response.json()
        assert data["email"] == "invitee@example.com"
        assert data["role"] == "engineer"
        assert "code" in data

        # List invites
        list_response = await client.get("/api/v1/accounts/me/invites", headers=auth_headers)
        assert list_response.status_code == 200
        invites = list_response.json()
        assert len(invites) >= 1
        assert any(i["email"] == "invitee@example.com" for i in invites)

    @pytest.mark.asyncio
    async def test_register_with_account_invite(self, client: AsyncClient, auth_headers: dict):
        """Test that account invite code joins user to existing account."""
        # Get current account
        account_resp = await client.get("/api/v1/accounts/me", headers=auth_headers)
        account_id = account_resp.json()["id"]

        # Create invite
        invite_resp = await client.post(
            "/api/v1/accounts/me/invites",
            json={"email": "joiner@example.com", "role": "viewer"},
            headers=auth_headers
        )
        invite_code = invite_resp.json()["code"]

        # Register with account invite code
        reg_resp = await client.post("/api/v1/auth/register", json={
            "email": "joiner@example.com",
            "password": "JoinerPass123!",
            "name": "Joiner",
            "account_invite_code": invite_code
        })
        assert reg_resp.status_code == 201
        data = reg_resp.json()
        assert data["account_id"] == account_id
        assert data["account_role"] == "viewer"

    @pytest.mark.asyncio
    async def test_register_with_invalid_invite_code(self, client: AsyncClient):
        """Test that invalid account invite code is rejected."""
        response = await client.post("/api/v1/auth/register", json={
            "email": "bad@example.com",
            "password": "BadPassword123!",
            "name": "Bad User",
            "account_invite_code": "INVALID_CODE"
        })
        assert response.status_code == 400
        assert "invalid" in response.json()["detail"].lower()
