"""Changing your own password (POST /auth/password, app/routers/auth.py)."""

from sqlalchemy import text

from tests.conftest import TEST_ADMIN_PASSWORD, AsyncSessionLocal


def _login(tenant, password):
    return {"tenant_id": str(tenant["tenant_id"]), "email": tenant["admin_email"], "password": password}


async def test_you_change_your_password_with_the_current_one(client, test_tenant, auth_headers):
    resp = await client.post("/auth/password", headers=auth_headers, json={"current_password": TEST_ADMIN_PASSWORD, "new_password": "a-brand-new-pass"})
    assert resp.status_code == 204, resp.text
    assert (await client.post("/auth/login", json=_login(test_tenant, TEST_ADMIN_PASSWORD))).status_code == 401
    assert (await client.post("/auth/login", json=_login(test_tenant, "a-brand-new-pass"))).status_code == 200
    async with AsyncSessionLocal() as db:
        actions = set((await db.execute(text("SELECT action FROM audit_log_entries WHERE tenant_id = :t"), {"t": test_tenant["tenant_id"]})).scalars())
    assert "user.password_changed" in actions


async def test_a_wrong_current_password_counts_toward_the_lockout(client, test_tenant, auth_headers):
    bad = {"current_password": "not-my-password", "new_password": "a-brand-new-pass"}
    resp = await client.post("/auth/password", headers=auth_headers, json=bad)
    assert resp.status_code == 400 and resp.json()["detail"] == "Your current password is incorrect."
    async with AsyncSessionLocal() as db:
        failed = (await db.execute(text("SELECT failed_sign_ins FROM users WHERE id = :u"), {"u": test_tenant["admin_id"]})).scalar()
    assert failed == 1
    # Too short, or the same as now.
    assert (await client.post("/auth/password", headers=auth_headers, json={"current_password": TEST_ADMIN_PASSWORD, "new_password": "short"})).status_code == 422
    same = await client.post("/auth/password", headers=auth_headers, json={"current_password": TEST_ADMIN_PASSWORD, "new_password": TEST_ADMIN_PASSWORD})
    assert same.status_code == 422
