"""Tests for sre_beacon.calculators.availability_calculator."""

import math

import pytest

from sre_beacon.calculators.availability_calculator import (
    calculate_availability,
    calculate_composite_availability,
    downtime_for_nines,
)
from sre_beacon.models import AvailabilityInput


class TestCalculateAvailability:
    def test_healthy_service(self, availability_input_healthy):
        result = calculate_availability(availability_input_healthy)
        assert result.availability_pct > 99.9
        assert result.nines > 3.5
        assert result.uptime_minutes == 43195

    def test_degraded_service(self, availability_input_degraded):
        result = calculate_availability(availability_input_degraded)
        assert result.availability_pct == 99.0
        assert result.nines == 2.0
        assert result.downtime_minutes == 432

    def test_zero_downtime(self):
        inp = AvailabilityInput(service="perfect", total_minutes=43200, downtime_minutes=0)
        result = calculate_availability(inp)
        assert result.availability_pct == 100.0
        assert math.isinf(result.nines)

    def test_full_downtime(self):
        inp = AvailabilityInput(service="dead", total_minutes=43200, downtime_minutes=43200)
        result = calculate_availability(inp)
        assert result.availability_pct == 0.0
        assert result.nines == 0.0

    def test_nines_comparison_table(self, availability_input_healthy):
        result = calculate_availability(availability_input_healthy)
        assert 2 in result.allowed_downtime_by_nines
        assert 3 in result.allowed_downtime_by_nines
        assert result.allowed_downtime_by_nines[3]["meets"] is True  # 5 min < 43 min


class TestCompositeAvailability:
    def test_serial_two_services(self):
        inp1 = AvailabilityInput(service="a", total_minutes=43200, downtime_minutes=43)
        inp2 = AvailabilityInput(service="b", total_minutes=43200, downtime_minutes=43)
        r1 = calculate_availability(inp1)
        r2 = calculate_availability(inp2)
        composite = calculate_composite_availability([r1, r2])
        # Each ~99.9%, serial: ~99.8%
        assert composite < r1.availability_pct
        assert composite > 99.7

    def test_empty(self):
        assert calculate_composite_availability([]) == 0.0


class TestDowntimeForNines:
    def test_three_nines_30_days(self):
        dt = downtime_for_nines(3, period_days=30)
        assert abs(dt - 43.2) < 0.1

    def test_five_nines_30_days(self):
        dt = downtime_for_nines(5, period_days=30)
        assert dt < 1.0  # less than 1 minute

    def test_zero_nines(self):
        dt = downtime_for_nines(0, period_days=30)
        assert dt == 43200  # all downtime
