import pytest
from httpx import AsyncClient

pytestmark = pytest.mark.asyncio

REGISTER_URL = "/api/v1/auth/register"
LOGIN_URL = "/api/v1/auth/login"
REFRESH_URL = "/api/v1/auth/refresh"
LOGOUT_URL = "/api/v1/auth/logout"
RESET_URL = "/api/v1/auth/password-reset"
ME_URL = "/api/v1/auth/me"


async def test_register_success(client: AsyncClient):
    resp = await client.post(REGISTER_URL, json={
        "company_name": "Acme GmbH",
        "first_name": "Erika",
        "last_name": "Muster",
        "email": "erika@acme.de",
        "password": "Secure123",
    })
    assert resp.status_code == 201
    body = resp.json()
    assert "access_token" in body
    assert "refresh_token" in body
    assert body["token_type"] == "bearer"


async def test_register_duplicate_email(client: AsyncClient, registered_user):
    resp = await client.post(REGISTER_URL, json={
        "company_name": "Other GmbH",
        "first_name": "Max",
        "last_name": "Mustermann",
        "email": registered_user["user"]["email"],
        "password": "Secret123",
    })
    assert resp.status_code == 400
    assert "already registered" in resp.json()["detail"]


async def test_register_weak_password(client: AsyncClient):
    resp = await client.post(REGISTER_URL, json={
        "company_name": "Weak Corp",
        "first_name": "A",
        "last_name": "B",
        "email": "weak@corp.de",
        "password": "nouppercase1",
    })
    assert resp.status_code == 422


async def test_login_success(client: AsyncClient, registered_user):
    resp = await client.post(LOGIN_URL, json={
        "email": registered_user["user"]["email"],
        "password": "Secret123",
    })
    assert resp.status_code == 200
    assert "access_token" in resp.json()


async def test_login_wrong_password(client: AsyncClient, registered_user):
    resp = await client.post(LOGIN_URL, json={
        "email": registered_user["user"]["email"],
        "password": "WrongPassword1",
    })
    assert resp.status_code == 401


async def test_login_unknown_email(client: AsyncClient):
    resp = await client.post(LOGIN_URL, json={
        "email": "nobody@nowhere.de",
        "password": "Secret123",
    })
    assert resp.status_code == 401


async def test_me_authenticated(client: AsyncClient, registered_user):
    resp = await client.get(
        ME_URL,
        headers={"Authorization": f"Bearer {registered_user['tokens']['access_token']}"},
    )
    assert resp.status_code == 200
    body = resp.json()
    assert body["email"] == registered_user["user"]["email"]
    assert body["role"] == "COMPANY_ADMIN"


async def test_me_unauthenticated(client: AsyncClient):
    resp = await client.get(ME_URL)
    assert resp.status_code == 401


async def test_token_refresh(client: AsyncClient, registered_user):
    resp = await client.post(REFRESH_URL, json={
        "refresh_token": registered_user["tokens"]["refresh_token"],
    })
    assert resp.status_code == 200
    new_tokens = resp.json()
    assert "access_token" in new_tokens
    # Old refresh token should now be invalid (rotation)
    resp2 = await client.post(REFRESH_URL, json={
        "refresh_token": registered_user["tokens"]["refresh_token"],
    })
    assert resp2.status_code == 401


async def test_logout(client: AsyncClient):
    reg = await client.post(REGISTER_URL, json={
        "company_name": "Logout Corp",
        "first_name": "Hans",
        "last_name": "Logout",
        "email": "hans@logout.de",
        "password": "Secret123",
    })
    tokens = reg.json()
    resp = await client.post(LOGOUT_URL, json={"refresh_token": tokens["refresh_token"]})
    assert resp.status_code == 200
    # Refresh should now fail
    resp2 = await client.post(REFRESH_URL, json={"refresh_token": tokens["refresh_token"]})
    assert resp2.status_code == 401


async def test_password_reset_request(client: AsyncClient, registered_user):
    resp = await client.post(RESET_URL, json={"email": registered_user["user"]["email"]})
    assert resp.status_code == 200
    # Same response for unknown email (anti-enumeration)
    resp2 = await client.post(RESET_URL, json={"email": "nobody@x.de"})
    assert resp2.status_code == 200
