"""GET /api/v1/orchestrator/events/stats — failure-count badge endpoint (DEBT-042)."""
from __future__ import annotations

from datetime import datetime, timedelta, timezone
from unittest.mock import AsyncMock, patch

import httpx
import pytest

from decnet.web.api import app

_V1 = "/api/v1/orchestrator"


@pytest.mark.anyio
async def test_stats_unauthenticated_401():
    async with httpx.AsyncClient(
        transport=httpx.ASGITransport(app=app), base_url="http://test",
    ) as ac:
        r = await ac.get(f"{_V1}/events/stats?since=1h&success=false")
        assert r.status_code == 401


@pytest.mark.asyncio
async def test_stats_returns_failure_count_with_window():
    from decnet.web.router.orchestrator.api_event_stats import (
        orchestrator_event_stats,
    )

    with patch(
        "decnet.web.router.orchestrator.api_event_stats.repo"
    ) as mock_repo:
        mock_repo.count_orchestrator_failures = AsyncMock(return_value=7)

        result = await orchestrator_event_stats(
            since="1h", success=False, kind=None,
            user={"uuid": "u", "role": "viewer"},
        )

    assert result["count"] == 7
    assert result["since"] == "1h"
    assert result["success"] is False
    assert result["kind"] is None

    # Window must be "now - 1h", not 5h or 30s. Tolerance of 5 seconds
    # for the test execution.
    call = mock_repo.count_orchestrator_failures.await_args
    since_ts = call.kwargs["since_ts"]
    expected = datetime.now(timezone.utc) - timedelta(hours=1)
    assert abs((since_ts - expected).total_seconds()) < 5


@pytest.mark.asyncio
async def test_stats_forwards_kind_filter():
    from decnet.web.router.orchestrator.api_event_stats import (
        orchestrator_event_stats,
    )

    with patch(
        "decnet.web.router.orchestrator.api_event_stats.repo"
    ) as mock_repo:
        mock_repo.count_orchestrator_failures = AsyncMock(return_value=2)

        await orchestrator_event_stats(
            since="15m", success=False, kind="email",
            user={"uuid": "u", "role": "viewer"},
        )

    assert mock_repo.count_orchestrator_failures.await_args.kwargs["kind"] == "email"


@pytest.mark.asyncio
async def test_stats_rejects_success_true():
    """Only success=false is supported on this surface today; everything
    else is rejected so the endpoint isn't accidentally repurposed
    before the next consumer is properly designed."""
    from fastapi import HTTPException

    from decnet.web.router.orchestrator.api_event_stats import (
        orchestrator_event_stats,
    )

    with pytest.raises(HTTPException) as exc:
        await orchestrator_event_stats(
            since="1h", success=True, kind=None,
            user={"uuid": "u", "role": "viewer"},
        )
    assert exc.value.status_code == 422


@pytest.mark.asyncio
async def test_stats_rejects_success_unset():
    from fastapi import HTTPException

    from decnet.web.router.orchestrator.api_event_stats import (
        orchestrator_event_stats,
    )

    with pytest.raises(HTTPException) as exc:
        await orchestrator_event_stats(
            since="1h", success=None, kind=None,
            user={"uuid": "u", "role": "viewer"},
        )
    assert exc.value.status_code == 422


@pytest.mark.asyncio
async def test_stats_rejects_malformed_since():
    from fastapi import HTTPException

    from decnet.web.router.orchestrator.api_event_stats import (
        orchestrator_event_stats,
    )

    with pytest.raises(HTTPException) as exc:
        await orchestrator_event_stats(
            since="garbage", success=False, kind=None,
            user={"uuid": "u", "role": "viewer"},
        )
    assert exc.value.status_code == 422


@pytest.mark.asyncio
async def test_stats_rejects_window_over_max():
    from fastapi import HTTPException

    from decnet.web.router.orchestrator.api_event_stats import (
        orchestrator_event_stats,
    )

    with pytest.raises(HTTPException) as exc:
        await orchestrator_event_stats(
            since="30d", success=False, kind=None,
            user={"uuid": "u", "role": "viewer"},
        )
    assert exc.value.status_code == 422
