"""Tests for system endpoints: /health, /v1/models, /v1/budget, /metrics."""

from unittest.mock import MagicMock, patch

import pytest


class TestHealthEndpoint:
    """Tests for /health endpoint."""

    def test_health_returns_ok(self, client):
        """Health endpoint returns status ok."""
        response = client.get("/health")

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "ok"

    def test_health_includes_version(self, client):
        """Health endpoint includes version info."""
        response = client.get("/health")

        assert response.status_code == 200
        data = response.json()
        assert "version" in data
        assert isinstance(data["version"], str)


class TestModelsEndpoint:
    """Tests for /v1/models endpoint."""

    def test_list_models_returns_all_models(self, authed_client):
        """List models returns all available models."""
        response = authed_client.get("/v1/models")

        assert response.status_code == 200
        data = response.json()
        assert "data" in data
        assert isinstance(data["data"], list)
        assert len(data["data"]) > 0

        # Check model structure
        model = data["data"][0]
        assert "id" in model
        assert "owned_by" in model
        assert "input_cost_per_1m" in model
        assert "output_cost_per_1m" in model
        assert "context_window" in model

    def test_list_models_filters_by_available_providers(self, authed_client, settings):
        """Models are filtered by configured providers only."""
        response = authed_client.get("/v1/models")

        assert response.status_code == 200
        data = response.json()

        # Get configured providers
        configured = settings.available_providers()

        # All returned models should be from configured providers
        for model in data["data"]:
            assert model["owned_by"] in configured


class TestBudgetEndpoint:
    """Tests for /v1/budget endpoint."""

    def test_budget_status_shows_remaining(self, authed_client):
        """Budget endpoint shows remaining budget."""
        response = authed_client.get("/v1/budget")

        assert response.status_code == 200
        data = response.json()

        assert "daily_remaining_usd" in data
        assert "monthly_remaining_usd" in data
        assert "daily_limit_usd" in data
        assert "monthly_limit_usd" in data

    def test_budget_status_warns_when_near_limit(self, authed_client):
        """Budget status shows warning when near limit."""
        with patch("proxym.api.system.get_cost_ledger") as mock_ledger:
            # Mock budget near limit
            mock_ledger.return_value = MagicMock(
                daily_remaining=0.5,
                monthly_remaining=2.0,
                daily_limit=5.0,
                monthly_limit=60.0,
            )

            response = authed_client.get("/v1/budget")

        assert response.status_code == 200
        data = response.json()

        # When budget is low, should have warning indicator
        assert "daily_remaining_usd" in data
        assert data["daily_remaining_usd"] < 1.0  # Less than $1 remaining


class TestMetricsEndpoint:
    """Tests for /metrics endpoint."""

    def test_metrics_returns_prometheus_format(self, authed_client):
        """Metrics endpoint returns Prometheus-compatible format."""
        response = authed_client.get("/metrics")

        # Should return either 200 with metrics or 404 if not implemented
        assert response.status_code in [200, 404]

        if response.status_code == 200:
            content = response.text
            # Prometheus format lines start with metric names or comments
            lines = content.strip().split("\n")
            assert len(lines) > 0


class TestSystemIntegration:
    """Integration tests across system endpoints."""

    def test_all_system_endpoints_available(self, client, authed_client):
        """All system endpoints are available and return correct status codes."""
        # Public endpoints
        public_endpoints = [
            ("/health", 200),
            ("/docs", 200),  # Swagger UI
            ("/openapi.json", 200),
        ]

        # Protected endpoints
        protected_endpoints = [
            ("/v1/models", 401, 200),  # Without auth / With auth
            ("/v1/budget", 401, 200),
        ]

        # Test public
        for endpoint, expected in public_endpoints:
            response = client.get(endpoint)
            assert response.status_code == expected, f"{endpoint} failed"

        # Test protected without auth
        for endpoint, without_auth, with_auth in protected_endpoints:
            response = client.get(endpoint)
            assert response.status_code == without_auth, f"{endpoint} without auth failed"

        # Test protected with auth
        for endpoint, without_auth, with_auth in protected_endpoints:
            response = authed_client.get(endpoint)
            assert response.status_code == with_auth, f"{endpoint} with auth failed"
