"""Tests for self-healing configuration and event endpoints."""

from unittest.mock import AsyncMock, patch


class TestGetSelfHealConfig:
    """Tests for GET /v1/self-heal/config."""

    def test_get_config_exists(self, client, auth_header):
        with patch("api.db.get_self_heal_config", new_callable=AsyncMock) as mock_config:
            mock_config.return_value = {
                "enabled": True,
                "auto_pr": True,
                "auto_merge": False,
                "min_confidence": 0.9,
                "require_approvals": 1,
                "excluded_paths": [],
                "included_branches": ["main"],
                "slack_webhook_url": None,
                "linear_team_id": None,
                "max_prs_per_day": 5,
                "max_fixes_per_test": 3,
            }
            response = client.get("/v1/self-heal/config", headers=auth_header)
            assert response.status_code == 200
            data = response.json()
            assert data["enabled"] is True
            assert data["auto_pr"] is True

    def test_get_config_default(self, client, auth_header):
        with patch("api.db.get_self_heal_config", new_callable=AsyncMock) as mock_config:
            mock_config.return_value = None
            response = client.get("/v1/self-heal/config", headers=auth_header)
            assert response.status_code == 200
            data = response.json()
            assert data["enabled"] is False
            assert data["min_confidence"] == 0.9

    def test_get_config_unauthorized(self, client):
        response = client.get("/v1/self-heal/config")
        assert response.status_code == 401


class TestUpdateSelfHealConfig:
    """Tests for PUT /v1/self-heal/config."""

    def test_update_config_success(self, client, auth_header):
        with patch("api.db.upsert_self_heal_config", new_callable=AsyncMock) as mock_upsert:
            mock_upsert.return_value = None
            response = client.put(
                "/v1/self-heal/config",
                json={
                    "enabled": True,
                    "auto_pr": True,
                    "auto_merge": False,
                    "min_confidence": 0.85,
                    "require_approvals": 2,
                    "excluded_paths": ["tests/legacy/"],
                    "included_branches": ["main", "develop"],
                    "max_prs_per_day": 10,
                    "max_fixes_per_test": 5,
                },
                headers=auth_header,
            )
            assert response.status_code == 200
            data = response.json()
            assert data["enabled"] is True
            assert data["min_confidence"] == 0.85
            assert data["require_approvals"] == 2

    def test_update_config_unauthorized(self, client):
        response = client.put(
            "/v1/self-heal/config",
            json={"enabled": True},
        )
        assert response.status_code == 401


class TestTriggerSelfHeal:
    """Tests for POST /v1/runs/{run_id}/self-heal."""

    def test_trigger_self_heal_already_processed(self, client, auth_header):
        run_id = "550e8400-e29b-41d4-a716-446655440000"
        with patch("api.db.get_self_heal_event_by_run", new_callable=AsyncMock) as mock_event, \
             patch("api.db.get_run", new_callable=AsyncMock) as mock_run:
            mock_event.return_value = {
                "action": "fix_created",
                "fix_id": "fix_123",
                "pr_url": "https://github.com/org/repo/pull/1",
                "confidence": 0.95,
            }
            mock_run.return_value = {"id": run_id, "org_id": "org_test456"}
            response = client.post(
                f"/v1/runs/{run_id}/self-heal", headers=auth_header,
            )
            assert response.status_code == 200
            data = response.json()
            assert data["action"] == "fix_created"
            assert "idempotent" in data["reason"].lower()

    def test_trigger_self_heal_run_not_found(self, client, auth_header):
        run_id = "550e8400-e29b-41d4-a716-446655440000"
        with patch("api.db.get_self_heal_event_by_run", new_callable=AsyncMock) as mock_event, \
             patch("api.db.get_run", new_callable=AsyncMock) as mock_run:
            mock_event.return_value = None
            mock_run.return_value = None
            response = client.post(
                f"/v1/runs/{run_id}/self-heal", headers=auth_header,
            )
            assert response.status_code == 404

    def test_trigger_self_heal_unauthorized(self, client):
        run_id = "550e8400-e29b-41d4-a716-446655440000"
        response = client.post(f"/v1/runs/{run_id}/self-heal")
        assert response.status_code == 401


class TestGetSelfHealEvents:
    """Tests for GET /v1/self-heal/events."""

    def test_get_events_success(self, client, auth_header):
        with patch("api.db.get_self_heal_events", new_callable=AsyncMock) as mock_events:
            mock_events.return_value = [
                {
                    "id": "evt_1",
                    "run_id": "550e8400-e29b-41d4-a716-446655440000",
                    "test_name": "test_login",
                    "action": "fix_created",
                    "reason": "Flaky test detected",
                    "fix_id": "fix_1",
                    "pr_url": "https://github.com/org/repo/pull/1",
                    "confidence": 0.92,
                    "runs_passed": 10,
                    "runs_total": 10,
                    "created_at": "2025-01-15T10:00:00Z",
                },
            ]
            response = client.get("/v1/self-heal/events", headers=auth_header)
            assert response.status_code == 200
            data = response.json()
            assert len(data) == 1
            assert data[0]["action"] == "fix_created"

    def test_get_events_unauthorized(self, client):
        response = client.get("/v1/self-heal/events")
        assert response.status_code == 401


class TestGetSelfHealStats:
    """Tests for GET /v1/self-heal/stats."""

    def test_get_stats_success(self, client, auth_header):
        with patch("api.db.get_self_heal_stats", new_callable=AsyncMock) as mock_stats:
            mock_stats.return_value = {
                "total_events": 50,
                "fixes_generated": 30,
                "prs_created": 25,
                "prs_merged": 20,
                "fix_failures": 5,
                "skipped": 15,
                "success_rate": 0.8,
                "avg_confidence": 0.91,
            }
            response = client.get("/v1/self-heal/stats", headers=auth_header)
            assert response.status_code == 200
            data = response.json()
            assert data["total_events"] == 50
            assert data["success_rate"] == 0.8

    def test_get_stats_unauthorized(self, client):
        response = client.get("/v1/self-heal/stats")
        assert response.status_code == 401
