"""Per-server metric samples, offline segments, and API."""

from datetime import datetime, timedelta, timezone

import pytest

from server.utils.server_metrics import (
    merge_offline_segments,
    parse_system_info_metrics,
    sample_from_redis_heartbeat,
)


def test_parse_system_info_metrics():
    cpu, mem = parse_system_info_metrics({"cpu_usage": 12.4, "mem_usage": 55.6})
    assert cpu == 12
    assert mem == 56


def test_sample_from_redis_online():
    is_online, cpu, mem = sample_from_redis_heartbeat(
        {"is_online": "True", "system_info": '{"cpu_usage": 20, "mem_usage": 30}'}
    )
    assert is_online is True
    assert cpu == 20
    assert mem == 30


def test_sample_from_redis_offline():
    is_online, cpu, mem = sample_from_redis_heartbeat(
        {"is_online": "False", "system_info": '{"cpu_usage": 99, "mem_usage": 99}'}
    )
    assert is_online is False
    assert cpu is None
    assert mem is None


def test_merge_offline_segments():
    points = [
        {"recorded_at": "2026-06-09 10:00:00", "is_online": True},
        {"recorded_at": "2026-06-09 10:10:00", "is_online": False},
        {"recorded_at": "2026-06-09 10:20:00", "is_online": False},
        {"recorded_at": "2026-06-09 10:30:00", "is_online": True},
    ]
    segs = merge_offline_segments(points)
    assert len(segs) == 1
    assert segs[0]["from"] == "2026-06-09 10:10:00"
    assert segs[0]["to"] == "2026-06-09 10:20:00"


def test_merge_offline_segments_trailing_offline():
    points = [
        {"recorded_at": "2026-06-09 10:00:00", "is_online": True},
        {"recorded_at": "2026-06-09 10:10:00", "is_online": False},
    ]
    segs = merge_offline_segments(points)
    assert len(segs) == 1
    assert segs[0]["to"] == "2026-06-09 10:10:00"


@pytest.mark.asyncio
async def test_server_metrics_api(db_session, test_admin):
    from server.api.servers import get_server_metrics
    from server.application.services.server_service import ServerService
    from server.infrastructure.database.server_metric_repo import ServerMetricRepositoryImpl
    from server.infrastructure.database.server_repo import ServerRepositoryImpl
    from server.infrastructure.database.sync_log_repo import SyncLogRepositoryImpl
    from server.domain.models import Server

    server = Server(
        name="metric-test",
        domain="metric.example.com",
        port=22,
        agent_version="1.0.0",
    )
    db_session.add(server)
    await db_session.flush()

    repo = ServerMetricRepositoryImpl(db_session)
    now = datetime.now(timezone.utc)
    await repo.insert_sample(
        server_id=server.id,
        recorded_at=now - timedelta(minutes=20),
        is_online=True,
        cpu_pct=10,
        mem_pct=20,
    )
    await repo.insert_sample(
        server_id=server.id,
        recorded_at=now - timedelta(minutes=10),
        is_online=False,
        cpu_pct=None,
        mem_pct=None,
    )
    await db_session.commit()

    service = ServerService(
        ServerRepositoryImpl(db_session),
        SyncLogRepositoryImpl(db_session),
    )
    body = await get_server_metrics(
        id=server.id,
        hours=24,
        admin=test_admin["admin"],
        service=service,
        db=db_session,
    )
    assert body["server_id"] == server.id
    assert body["hours"] == 24
    assert body["interval_minutes"] == 10
    assert len(body["points"]) >= 2
    assert len(body["offline_segments"]) >= 1


@pytest.mark.asyncio
async def test_server_metrics_api_not_found(db_session, test_admin):
    from server.api.servers import get_server_metrics
    from server.application.services.server_service import ServerService
    from server.infrastructure.database.server_repo import ServerRepositoryImpl
    from server.infrastructure.database.sync_log_repo import SyncLogRepositoryImpl
    from fastapi import HTTPException

    service = ServerService(
        ServerRepositoryImpl(db_session),
        SyncLogRepositoryImpl(db_session),
    )
    with pytest.raises(HTTPException) as exc:
        await get_server_metrics(
            id=999999,
            hours=24,
            admin=test_admin["admin"],
            service=service,
            db=db_session,
        )
    assert exc.value.status_code == 404
