"""Tests für Auszahlungs-Anträge mit Genehmigung (router/hours_payouts.py)."""
import pytest
import pytest_asyncio
from httpx import AsyncClient


@pytest_asyncio.fixture(scope="session", loop_scope="session")
async def payout_headers(client: AsyncClient):
    resp = await client.post("/api/v1/auth/register", json={
        "company_name": "Payout GmbH",
        "first_name": "Paul",
        "last_name": "Out",
        "email": "admin@payoutgmbh.de",
        "password": "Secret123",
    })
    assert resp.status_code == 201, resp.text
    return {"Authorization": f"Bearer {resp.json()['access_token']}"}


@pytest.mark.asyncio(loop_scope="session")
async def test_request_disabled_by_default(client: AsyncClient, payout_headers):
    r = await client.post("/api/v1/hr/payouts/request",
                          json={"hours": 4}, headers=payout_headers)
    assert r.status_code == 403


@pytest.mark.asyncio(loop_scope="session")
async def test_enable_and_request_approve(client: AsyncClient, payout_headers):
    # Firma schaltet Selbstbedienung frei
    up = await client.patch("/api/v1/companies/me",
                            json={"payout_request_enabled": True}, headers=payout_headers)
    assert up.status_code == 200, up.text
    assert up.json()["payout_request_enabled"] is True

    # Antrag stellen – Status requested, kein Saldo-Abzug
    r = await client.post("/api/v1/hr/payouts/request",
                          json={"hours": 5, "note": "Bitte auszahlen"}, headers=payout_headers)
    assert r.status_code == 201, r.text
    pid = r.json()["id"]
    assert r.json()["status"] == "requested"

    bal = await client.get("/api/v1/absences/overtime-balance", headers=payout_headers)
    assert float(bal.json()["taken_hours"]) == 0.0

    # HR genehmigt – jetzt Saldo-Abzug
    ap = await client.post(f"/api/v1/hr/payouts/{pid}/approve", json={}, headers=payout_headers)
    assert ap.status_code == 200, ap.text
    assert ap.json()["status"] == "approved"

    bal2 = await client.get("/api/v1/absences/overtime-balance", headers=payout_headers)
    assert float(bal2.json()["taken_hours"]) == 5.0

    # Erneutes Genehmigen scheitert
    ap2 = await client.post(f"/api/v1/hr/payouts/{pid}/approve", json={}, headers=payout_headers)
    assert ap2.status_code == 409


@pytest.mark.asyncio(loop_scope="session")
async def test_reject_no_deduction(client: AsyncClient, payout_headers):
    r = await client.post("/api/v1/hr/payouts/request",
                          json={"hours": 3}, headers=payout_headers)
    pid = r.json()["id"]
    before = float((await client.get("/api/v1/absences/overtime-balance",
                                     headers=payout_headers)).json()["taken_hours"])

    rej = await client.post(f"/api/v1/hr/payouts/{pid}/reject",
                            json={"rejection_reason": "kein Budget"}, headers=payout_headers)
    assert rej.status_code == 200
    assert rej.json()["status"] == "rejected"
    assert rej.json()["rejection_reason"] == "kein Budget"

    after = float((await client.get("/api/v1/absences/overtime-balance",
                                    headers=payout_headers)).json()["taken_hours"])
    assert after == before  # kein Abzug bei Ablehnung


@pytest.mark.asyncio(loop_scope="session")
async def test_cancel_own_request(client: AsyncClient, payout_headers):
    r = await client.post("/api/v1/hr/payouts/request",
                          json={"hours": 2}, headers=payout_headers)
    pid = r.json()["id"]
    c = await client.post(f"/api/v1/hr/payouts/{pid}/cancel", json={}, headers=payout_headers)
    assert c.status_code == 200
    assert c.json()["status"] == "cancelled"
    # Genehmigen eines zurückgezogenen Antrags scheitert
    ap = await client.post(f"/api/v1/hr/payouts/{pid}/approve", json={}, headers=payout_headers)
    assert ap.status_code == 409
