from tests.fixtures import make_test_png
from tests.helpers import latest_token, register_and_verify, register_verify_login


def _admin_headers(client) -> dict[str, str]:
    login = client.post(
        "/api/v1/auth/login",
        json={"email": "admin@compton.example", "password": "Admin1234"},
    )
    token = login.json()["access_token"]
    return {"Authorization": f"Bearer {token}"}


def test_auth_refresh_and_logout(client):
    register_and_verify(client, "refresh@example.com")
    login = client.post(
        "/api/v1/auth/login",
        json={"email": "refresh@example.com", "password": "Valid123"},
    )
    assert login.status_code == 200
    assert "refresh_token" in login.cookies

    refresh = client.post("/api/v1/auth/refresh", headers={"Origin": "http://localhost:5173"})
    assert refresh.status_code == 200
    assert "access_token" in refresh.json()

    logout = client.post("/api/v1/auth/logout", headers={"Origin": "http://localhost:5173"})
    assert logout.status_code == 200


def test_auth_invalid_login(client):
    response = client.post(
        "/api/v1/auth/login",
        json={"email": "missing@example.com", "password": "Valid123"},
    )
    assert response.status_code == 401


def test_users_patch_and_password_and_avatar(client):
    headers = register_verify_login(client, "patch@example.com")
    patch = client.patch("/api/v1/users/me", headers=headers, json={"display_name": "Patched"})
    assert patch.status_code == 200
    assert patch.json()["profile"]["display_name"] == "Patched"

    bad_password = client.post(
        "/api/v1/users/me/password",
        headers=headers,
        json={"current_password": "wrong", "new_password": "NewValid1"},
    )
    assert bad_password.status_code == 400

    avatar = client.post(
        "/api/v1/users/me/avatar",
        headers=headers,
        files={"file": ("avatar.png", make_test_png(), "image/png")},
    )
    assert avatar.status_code == 200
    assert avatar.json()["profile"]["avatar_url"]


def test_users_unauthorized(client):
    response = client.get("/api/v1/users/me")
    assert response.status_code == 401


def test_content_crud_flow(client):
    headers = _admin_headers(client)
    created = client.post(
        "/api/v1/content/pages",
        headers=headers,
        json={"slug": "terms", "title": "Terms", "body": "<p>Terms</p>", "status": "draft"},
    )
    assert created.status_code == 200
    page_id = created.json()["id"]

    listed = client.get("/api/v1/content/pages")
    assert listed.status_code == 200

    updated = client.patch(
        f"/api/v1/content/pages/{page_id}",
        headers=headers,
        json={"status": "published"},
    )
    assert updated.status_code == 200

    fetched = client.get("/api/v1/content/pages/terms")
    assert fetched.status_code == 200

    deleted = client.delete(f"/api/v1/content/pages/{page_id}", headers=headers)
    assert deleted.status_code == 200


def test_admin_stats_and_patch_user(client):
    headers = _admin_headers(client)
    stats = client.get("/api/v1/admin/stats", headers=headers)
    assert stats.status_code == 200

    user_headers = register_verify_login(client, "blockme@example.com")
    me = client.get("/api/v1/users/me", headers=user_headers)
    user_id = me.json()["user"]["id"]

    blocked = client.patch(
        f"/api/v1/admin/users/{user_id}",
        headers=headers,
        json={"status": "blocked"},
    )
    assert blocked.status_code == 200
    assert blocked.json()["status"] == "blocked"


def test_auth_pending_user_cannot_login(client):
    client.post("/api/v1/auth/register", json={"email": "pending@example.com", "password": "Valid123"})
    response = client.post(
        "/api/v1/auth/login",
        json={"email": "pending@example.com", "password": "Valid123"},
    )
    assert response.status_code == 403
    assert response.json()["detail"] == "EMAIL_NOT_VERIFIED"


def test_pending_user_cannot_access_profile(client):
    from app.core.security import create_access_token
    from app.modules.users.repository import get_user_by_email

    client.post("/api/v1/auth/register", json={"email": "pendingme@example.com", "password": "Valid123"})
    user = get_user_by_email("pendingme@example.com")
    token = create_access_token(user.id, user.role)
    response = client.get("/api/v1/users/me", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 403
    assert response.json()["detail"] == "EMAIL_NOT_VERIFIED"


def test_auth_invalid_refresh_token(client):
    response = client.post("/api/v1/auth/refresh")
    assert response.status_code == 401

    client.cookies.set("refresh_token", "invalid-token", path="/api/v1/auth")
    invalid = client.post("/api/v1/auth/refresh", headers={"Origin": "http://localhost:5173"})
    assert invalid.status_code == 401


def test_auth_resend_and_reset_password(client):
    client.post("/api/v1/auth/register", json={"email": "resetme@example.com", "password": "Valid123"})
    resend = client.post("/api/v1/auth/resend-verification", json={"email": "resetme@example.com"})
    assert resend.status_code == 200
    verify_token = latest_token("resetme@example.com", "verify_email")
    verify = client.post("/api/v1/auth/verify-email", json={"token": verify_token})
    assert verify.status_code == 200

    forgot = client.post("/api/v1/auth/forgot-password", json={"email": "resetme@example.com"})
    assert forgot.status_code == 200
    reset_token = latest_token("resetme@example.com", "reset_password")

    reset = client.post(
        "/api/v1/auth/reset-password",
        json={"token": reset_token, "new_password": "NewValid1"},
    )
    assert reset.status_code == 200

    login = client.post(
        "/api/v1/auth/login",
        json={"email": "resetme@example.com", "password": "NewValid1"},
    )
    assert login.status_code == 200

    invalid = client.post(
        "/api/v1/auth/reset-password",
        json={"token": "invalid-token", "new_password": "NewValid1"},
    )
    assert invalid.status_code == 400
