"""
Integration tests for OTel Collector healthcheck functionality.

Tests validate that the /health/status endpoint works correctly
and reports accurate collector status.
"""

import subprocess
import time
import pytest
import requests


class TestHealthcheck:
    """Test suite for healthcheck endpoint validation."""

    @pytest.fixture(scope="class", autouse=True)
    def ensure_collector_running(self, project_root):
        """
        Ensure collector is running before tests.

        Starts collector if not already running and waits for healthy state.
        """
        # Check if already running
        result = subprocess.run(
            [
                "docker",
                "ps",
                "--filter",
                "name=mca-otel-collector",
                "--format",
                "{{.Names}}",
            ],
            capture_output=True,
            text=True,
        )

        if "mca-otel-collector" not in result.stdout:
            # Start collector
            subprocess.run(
                ["docker-compose", "up", "-d", "otel-collector"],
                cwd=str(project_root),
                capture_output=True,
            )

        # Wait for healthy state
        max_wait = 30
        start_time = time.time()

        while time.time() - start_time < max_wait:
            health_result = subprocess.run(
                [
                    "docker",
                    "inspect",
                    "--format",
                    "{{.State.Health.Status}}",
                    "mca-otel-collector",
                ],
                capture_output=True,
                text=True,
            )

            if health_result.returncode == 0 and health_result.stdout.strip() == "healthy":
                break

            time.sleep(2)

        yield

    def test_healthcheck_endpoint_returns_200(self):
        """
        Test that healthcheck endpoint returns HTTP 200.

        Validates:
        - Endpoint is accessible
        - Returns successful status code
        """
        response = requests.get("http://localhost:13133/", timeout=5)

        assert (
            response.status_code == 200
        ), f"Healthcheck endpoint returned {response.status_code}, expected 200"

    def test_healthcheck_endpoint_json_format(self):
        """
        Test that healthcheck endpoint returns valid JSON response.

        Validates:
        - Response is valid JSON
        - Contains expected status fields
        """
        response = requests.get("http://localhost:13133/", timeout=5)

        assert response.status_code == 200, "Healthcheck endpoint not accessible"

        # Try to parse JSON (OTel healthcheck may return JSON or plain text)
        content_type = response.headers.get("Content-Type", "")

        if "application/json" in content_type:
            data = response.json()
            # Verify it's a dict (valid JSON structure)
            assert isinstance(data, dict), "Response is not valid JSON object"
        else:
            # Plain text response is also acceptable (e.g., "ok")
            assert len(response.text) > 0, "Empty response from healthcheck"

    def test_docker_healthcheck_uses_wget_with_semantic_check(self):
        """Test that Docker healthcheck validates pipeline readiness."""
        result = subprocess.run(
            [
                "docker",
                "inspect",
                "--format",
                "{{json .Config.Healthcheck}}",
                "mca-otel-collector",
            ],
            capture_output=True,
            text=True,
        )

        assert result.returncode == 0, "Failed to inspect healthcheck config"
        healthcheck_config = result.stdout.strip()

        # Verify uses wget
        assert "wget" in healthcheck_config, "Healthcheck does not use wget command"

        # Verify semantic validation (not just HTTP ping)
        assert (
            '"status":"ready"' in healthcheck_config or "'status':'ready'" in healthcheck_config
        ), "Healthcheck does not validate pipeline readiness (status:ready)"

        # Verify uses grep for validation
        assert "grep" in healthcheck_config, "Healthcheck does not use grep for status validation"

    def test_healthcheck_interval_is_configured(self):
        """
        Test that healthcheck has reasonable interval configuration.

        Validates:
        - Interval is set (not default)
        - Timeout is configured
        - Retries are configured
        """
        result = subprocess.run(
            [
                "docker",
                "inspect",
                "--format",
                "{{json .Config.Healthcheck}}",
                "mca-otel-collector",
            ],
            capture_output=True,
            text=True,
        )

        assert result.returncode == 0, "Failed to inspect healthcheck config"

        import json

        healthcheck_config = json.loads(result.stdout)

        # Check interval exists (in nanoseconds)
        assert "Interval" in healthcheck_config, "Healthcheck interval not configured"
        interval_ns = healthcheck_config["Interval"]
        # 10 seconds = 10000000000 nanoseconds
        assert interval_ns == 10000000000, f"Unexpected interval: {interval_ns}ns (expected 10s)"

        # Check timeout exists
        assert "Timeout" in healthcheck_config, "Healthcheck timeout not configured"
        timeout_ns = healthcheck_config["Timeout"]
        # 5 seconds = 5000000000 nanoseconds
        assert timeout_ns == 5000000000, f"Unexpected timeout: {timeout_ns}ns (expected 5s)"

        # Check retries
        assert "Retries" in healthcheck_config, "Healthcheck retries not configured"
        retries = healthcheck_config["Retries"]
        assert retries == 5, f"Unexpected retries: {retries} (expected 5)"

    def test_healthcheck_start_period_is_configured(self):
        """
        Test that healthcheck has start period grace period.

        Validates:
        - Start period allows collector to initialize
        """
        result = subprocess.run(
            [
                "docker",
                "inspect",
                "--format",
                "{{json .Config.Healthcheck}}",
                "mca-otel-collector",
            ],
            capture_output=True,
            text=True,
        )

        assert result.returncode == 0, "Failed to inspect healthcheck config"

        import json

        healthcheck_config = json.loads(result.stdout)

        # Check start period exists
        assert "StartPeriod" in healthcheck_config, "Healthcheck start period not configured"
        start_period_ns = healthcheck_config["StartPeriod"]
        # 20 seconds = 20000000000 nanoseconds
        assert (
            start_period_ns == 20000000000
        ), f"Unexpected start period: {start_period_ns}ns (expected 20s)"

    def test_health_check_extension_is_configured(self):
        """
        Test that OTel Collector has health_check extension configured.

        Validates:
        - Config file includes health_check extension
        - Extension is enabled in service section
        """
        # Read config from container
        result = subprocess.run(
            [
                "docker",
                "exec",
                "mca-otel-collector",
                "cat",
                "/etc/otelcol-contrib/config.yaml",
            ],
            capture_output=True,
            text=True,
        )

        assert result.returncode == 0, "Failed to read config from container"

        config_content = result.stdout

        # Check for health_check extension
        assert (
            "health_check:" in config_content
        ), "health_check extension not configured in config.yaml"

        # Check extension is enabled in service
        assert (
            "extensions: [health_check]" in config_content
            or "extensions:\n    - health_check" in config_content
            or "extensions:\n  - health_check" in config_content
        ), "health_check extension not enabled in service section"

    def test_healthcheck_handles_concurrent_requests(self):
        """Test that healthcheck remains responsive under concurrent requests."""
        # Send multiple concurrent requests to healthcheck
        import concurrent.futures

        def check_health():
            try:
                response = requests.get("http://localhost:13133/", timeout=5)
                return response.status_code == 200
            except Exception:
                return False

        with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
            futures = [executor.submit(check_health) for _ in range(20)]
            results = [f.result() for f in concurrent.futures.as_completed(futures)]

        # All requests must succeed (100% success rate)
        success_count = sum(results)
        assert success_count == 20, (
            f"Only {success_count}/20 healthcheck requests succeeded. "
            f"Expected 100% success rate. Any failures indicate load handling issues."
        )

    def test_container_reports_healthy_status(self):
        """
        Test that Docker reports container as healthy.

        Validates:
        - Container health status is 'healthy'
        - Healthcheck has passed recently
        """
        result = subprocess.run(
            [
                "docker",
                "inspect",
                "--format",
                "{{.State.Health.Status}}",
                "mca-otel-collector",
            ],
            capture_output=True,
            text=True,
        )

        assert result.returncode == 0, "Failed to inspect container health status"

        health_status = result.stdout.strip()
        assert (
            health_status == "healthy"
        ), f"Container health status is '{health_status}', expected 'healthy'"

    def test_failing_healthcheck_count_is_zero(self):
        """
        Test that there are no recent healthcheck failures.

        Validates:
        - FailingStreak is 0
        - Healthcheck is consistently passing
        """
        result = subprocess.run(
            [
                "docker",
                "inspect",
                "--format",
                "{{.State.Health.FailingStreak}}",
                "mca-otel-collector",
            ],
            capture_output=True,
            text=True,
        )

        assert result.returncode == 0, "Failed to inspect healthcheck failures"

        failing_streak = result.stdout.strip()
        assert (
            failing_streak == "0"
        ), f"Container has {failing_streak} consecutive healthcheck failures"
