"""Tests for sre_beacon.calculators.slo_calculator."""

import pytest

from sre_beacon.calculators.slo_calculator import (
    calculate_slo,
    calculate_slos_from_yaml,
    load_slo_definitions,
    nines_from_target,
    project_error_budget_depletion,
)
from sre_beacon.models import SLIType, SLODefinition


class TestLoadSLODefinitions:
    def test_loads_from_yaml(self, tmp_yaml, slo_yaml_data):
        path = tmp_yaml(slo_yaml_data, "slos.yaml")
        slos = load_slo_definitions(path)
        assert len(slos) == 2
        assert slos[0].name == "API Availability"
        assert slos[0].sli_type == SLIType.AVAILABILITY
        assert slos[1].sli_type == SLIType.ERROR_RATE


class TestCalculateSLO:
    def test_compliant(self, sample_slo_definition):
        result = calculate_slo(sample_slo_definition, 99.95)
        assert result.compliant is True

    def test_non_compliant(self, sample_slo_definition):
        result = calculate_slo(sample_slo_definition, 99.5)
        assert result.compliant is False

    def test_burn_rate_stored(self, sample_slo_definition):
        result = calculate_slo(sample_slo_definition, 99.95, burn_rate=2.0)
        assert result.burn_rate == 2.0


class TestCalculateSLOsFromYAML:
    def test_full_flow(self, tmp_yaml, slo_yaml_data, actuals_yaml_data):
        slo_path = tmp_yaml(slo_yaml_data, "slos.yaml")
        act_path = tmp_yaml(actuals_yaml_data, "actuals.yaml")
        results = calculate_slos_from_yaml(slo_path, act_path)
        assert len(results) == 2
        # API Availability: 99.95 >= 99.9 → compliant
        assert results[0].compliant is True
        # Error Rate: 0.3 <= 0.5 → compliant
        assert results[1].compliant is True

    def test_no_matching_actuals(self, tmp_yaml, slo_yaml_data):
        slo_path = tmp_yaml(slo_yaml_data, "slos.yaml")
        act_path = tmp_yaml({"actuals": [{"name": "Unknown", "value": 99.0}]}, "actuals.yaml")
        results = calculate_slos_from_yaml(slo_path, act_path)
        assert len(results) == 0


class TestProjectErrorBudgetDepletion:
    def test_stable_when_no_burn(self, sample_slo_definition):
        result = calculate_slo(sample_slo_definition, 99.95, burn_rate=0)
        projection = project_error_budget_depletion(result)
        assert projection["status"] == "stable"

    def test_critical_burn(self, sample_slo_definition):
        result = calculate_slo(sample_slo_definition, 99.85, burn_rate=10.0)
        projection = project_error_budget_depletion(result)
        assert projection["status"] in ("critical", "warning")
        assert projection["depletes_in_days"] is not None


class TestNinesFromTarget:
    def test_three_nines(self):
        n = nines_from_target(99.9)
        assert abs(n - 3.0) < 0.01

    def test_four_nines(self):
        n = nines_from_target(99.99)
        assert abs(n - 4.0) < 0.01

    def test_hundred_percent(self):
        import math
        assert math.isinf(nines_from_target(100.0))
