"""CH-AGT-001 — heartbeat → Redis → dashboard online count."""

from __future__ import annotations

from unittest.mock import AsyncMock

import pytest

from server.api.agent import receive_heartbeat
from server.api.dependencies import get_server_service
from server.api.schemas import AgentHeartbeat
from server.api.servers import server_stats

pytestmark = pytest.mark.chain


@pytest.mark.asyncio
async def test_heartbeat_then_stats_online_count(
    db_session,
    test_server,
    test_admin,
    mock_request,
    monkeypatch,
):
    api_key = "chain-agent-key"
    test_server.agent_api_key = api_key
    await db_session.commit()

    stored: dict[str, dict] = {}

    async def fake_hset(key, mapping=None):
        if mapping:
            stored[key] = dict(mapping)

    async def fake_scan(cursor, match=None, count=200):
        keys = [k for k in stored if k.startswith("heartbeat:")]
        return 0, keys

    async def fake_hgetall(key):
        return stored.get(key, {})

    mock_redis = AsyncMock()
    mock_redis.hset = fake_hset
    mock_redis.expire = AsyncMock()
    mock_redis.get = AsyncMock(return_value=None)
    mock_redis.smembers = AsyncMock(return_value=set())
    mock_redis.sadd = AsyncMock()
    mock_redis.srem = AsyncMock()
    mock_redis.delete = AsyncMock()
    mock_redis.scan = fake_scan
    mock_redis.hgetall = fake_hgetall

    monkeypatch.setattr("server.api.agent.get_redis", lambda: mock_redis)
    monkeypatch.setattr("server.api.servers.get_redis", lambda: mock_redis)
    monkeypatch.setattr("server.api.agent.broadcast_alert", AsyncMock())
    monkeypatch.setattr("server.api.agent.broadcast_recovery", AsyncMock())
    monkeypatch.setattr("server.api.agent.send_telegram_system_alert", AsyncMock())

    mock_request.state.db = db_session
    service = await get_server_service(mock_request)

    hb = await receive_heartbeat(
        AgentHeartbeat(
            server_id=test_server.id,
            is_online=True,
            system_info={"cpu_usage": 10.0, "mem_usage": 20.0, "disk_usage": 30.0},
        ),
        api_key=api_key,
        service=service,
    )
    assert hb["status"] == "ok"

    stats = await server_stats(test_admin["admin"], db_session)
    assert stats["online"] >= 1
    assert stats["total"] >= 1
