"""Tests for API endpoints.

These tests use a test API key to authenticate requests.

IMPORTANT: These tests modify environment variables temporarily.
App is imported inside the fixture to avoid polluting global state.
"""

import importlib
import os
from unittest.mock import MagicMock, patch

import pytest
from fastapi.testclient import TestClient

# Test API key header
TEST_AUTH_HEADERS = {"X-API-Key": "test-api-key-for-unit-tests"}


@pytest.fixture
def client():
    """Create a test client for the FastAPI app with auth enabled."""
    # Store original env state
    original_env = {}
    for key in ["REQUIRE_API_AUTH", "API_KEYS"]:
        if key in os.environ:
            original_env[key] = os.environ[key]

    # Set test environment
    os.environ["REQUIRE_API_AUTH"] = "true"
    os.environ["API_KEYS"] = "test-api-key-for-unit-tests"

    # Reload security module to pick up new env vars
    from src.api import security

    importlib.reload(security)

    # Import app after setting env vars
    from src.api.main import app

    yield TestClient(app, raise_server_exceptions=False)

    # Restore original values
    for key in ["REQUIRE_API_AUTH", "API_KEYS"]:
        if key in original_env:
            os.environ[key] = original_env[key]
        elif key in os.environ:
            del os.environ[key]

    # Reload security to restore original state
    importlib.reload(security)


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

    def test_health_returns_status(self, client):
        """Test health endpoint returns status (no auth required)."""
        response = client.get("/health")
        assert response.status_code == 200
        data = response.json()
        assert "status" in data
        assert "version" in data

    def test_health_response_model(self, client):
        """Test health response matches model."""
        response = client.get("/health")
        assert response.status_code == 200
        data = response.json()
        # Verify all expected fields
        assert "status" in data
        assert "version" in data
        assert "llm_available" in data
        assert "validator_available" in data


class TestVersionEndpoint:
    """Tests for version endpoint."""

    def test_version_returns_info(self, client):
        """Test version endpoint returns version info."""
        response = client.get("/version")
        assert response.status_code == 200
        data = response.json()
        assert "version" in data


class TestValidationEndpoint:
    """Tests for validation endpoint."""

    def test_validate_valid_hed_string(self, client):
        """Test validation of valid HED string."""
        request_data = {
            "hed_string": "Sensory-event, Visual-presentation",
            "schema_version": "8.3.0",
        }
        response = client.post("/validate", json=request_data, headers=TEST_AUTH_HEADERS)
        # 200 if schema_loader initialized, 503 if not
        assert response.status_code in [200, 503]
        if response.status_code == 200:
            data = response.json()
            assert "is_valid" in data
            assert "errors" in data

    def test_validate_invalid_hed_string(self, client):
        """Test validation of invalid HED string."""
        request_data = {
            "hed_string": "CompletelyInvalidTag123",
            "schema_version": "8.3.0",
        }
        response = client.post("/validate", json=request_data, headers=TEST_AUTH_HEADERS)
        # 200 if schema_loader initialized, 503 if not
        assert response.status_code in [200, 503]
        if response.status_code == 200:
            data = response.json()
            # Should have some issues
            assert "is_valid" in data

    def test_validate_empty_string(self, client):
        """Test validation of empty string."""
        request_data = {
            "hed_string": "",
            "schema_version": "8.3.0",
        }
        response = client.post("/validate", json=request_data, headers=TEST_AUTH_HEADERS)
        # 422 if empty string rejected by pydantic, 200/503 otherwise
        assert response.status_code in [200, 422, 503]

    def test_validate_without_auth(self, client):
        """Test validate endpoint without auth."""
        request_data = {
            "hed_string": "Event",
            "schema_version": "8.3.0",
        }
        response = client.post("/validate", json=request_data)
        assert response.status_code == 401


class TestAnnotateEndpoint:
    """Tests for annotation endpoint."""

    def test_annotate_with_auth(self, client):
        """Test annotate endpoint with auth."""
        request_data = {
            "description": "A red circle appears on the screen",
            "schema_version": "8.3.0",
        }
        response = client.post("/annotate", json=request_data, headers=TEST_AUTH_HEADERS)
        # May be 503 if workflow not initialized, or 200 if it is
        assert response.status_code in [200, 503]

    def test_annotate_with_invalid_auth(self, client):
        """Test annotate endpoint with invalid auth."""
        request_data = {
            "description": "A red circle appears on the screen",
            "schema_version": "8.3.0",
        }
        response = client.post(
            "/annotate",
            json=request_data,
            headers={"X-API-Key": "wrong-key"},
        )
        assert response.status_code == 401

    def test_annotate_missing_auth(self, client):
        """Test annotate endpoint with missing auth."""
        request_data = {
            "description": "A red circle appears on the screen",
            "schema_version": "8.3.0",
        }
        response = client.post("/annotate", json=request_data)
        assert response.status_code == 401


class TestImageAnnotateEndpoint:
    """Tests for image annotation endpoint."""

    def test_image_annotate_with_auth(self, client):
        """Test image annotation with auth."""
        # Use a minimal valid base64 PNG (1x1 red pixel)
        request_data = {
            "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
        }
        response = client.post("/annotate-from-image", json=request_data, headers=TEST_AUTH_HEADERS)
        # May be 503 if vision agent not initialized, or 200 if it is
        assert response.status_code in [200, 503]


class TestCORSHeaders:
    """Tests for CORS configuration."""

    def test_cors_preflight(self, client):
        """Test CORS preflight request."""
        response = client.options(
            "/health",
            headers={
                "Origin": "http://localhost:3000",
                "Access-Control-Request-Method": "GET",
            },
        )
        # OPTIONS should be handled by CORS middleware
        assert response.status_code in [200, 204, 405]


class TestSecurityHeaders:
    """Tests for security headers."""

    def test_security_headers_present(self, client):
        """Test that security headers are present in response."""
        response = client.get("/health")
        # Check security headers added by middleware
        headers = response.headers
        # X-Content-Type-Options should be present
        assert "x-content-type-options" in headers


class TestRequestValidation:
    """Tests for request validation."""

    def test_annotate_missing_description(self, client):
        """Test annotate endpoint with missing description."""
        request_data = {
            "schema_version": "8.3.0",
        }
        response = client.post("/annotate", json=request_data, headers=TEST_AUTH_HEADERS)
        assert response.status_code == 422  # Validation error

    def test_validate_missing_hed_string(self, client):
        """Test validate endpoint with missing HED string."""
        request_data = {
            "schema_version": "8.3.0",
        }
        response = client.post("/validate", json=request_data, headers=TEST_AUTH_HEADERS)
        assert response.status_code == 422  # Validation error


class TestRootEndpoint:
    """Tests for root endpoint."""

    def test_root_returns_api_info(self, client):
        """Test root endpoint returns API information."""
        response = client.get("/")
        assert response.status_code == 200
        data = response.json()
        assert "name" in data
        assert data["name"] == "HEDit API"
        assert "version" in data
        assert "description" in data
        assert "endpoints" in data

    def test_root_lists_endpoints(self, client):
        """Test root endpoint lists all available endpoints."""
        response = client.get("/")
        data = response.json()
        endpoints = data["endpoints"]
        assert "POST /annotate" in endpoints
        assert "POST /validate" in endpoints
        assert "GET /health" in endpoints
        assert "GET /version" in endpoints


class TestFeedbackEndpoint:
    """Tests for feedback endpoint."""

    def test_feedback_submission(self, client):
        """Test basic feedback submission (no auth required)."""
        request_data = {
            "type": "text",
            "description": "Test event description",
            "annotation": "Sensory-event, Visual-presentation",
            "is_valid": True,
            "is_faithful": True,
            "is_complete": True,
            "validation_errors": [],
            "validation_warnings": [],
            "user_comment": "This annotation looks good!",
        }
        response = client.post("/feedback", json=request_data)
        # Should succeed (200) - no auth required for feedback
        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert "feedback_id" in data
        assert "message" in data

    def test_feedback_minimal_submission(self, client):
        """Test feedback with minimal required fields."""
        request_data = {
            "type": "text",
            "description": "Test description",
            "annotation": "Test-annotation",
            "user_comment": "Test comment",
        }
        response = client.post("/feedback", json=request_data)
        assert response.status_code == 200

    def test_feedback_image_type(self, client):
        """Test feedback submission for image type."""
        request_data = {
            "type": "image",
            "description": "Image description",
            "image_description": "A cat sitting on a mat",
            "annotation": "Animal/Cat, Furnishing/Mat",
            "user_comment": "Image annotation feedback",
        }
        response = client.post("/feedback", json=request_data)
        assert response.status_code == 200

    def test_feedback_missing_fields(self, client):
        """Test feedback with missing required fields."""
        request_data = {
            "type": "text",
            # Missing description, annotation, user_comment
        }
        response = client.post("/feedback", json=request_data)
        assert response.status_code == 422  # Validation error


class TestMoreSecurityHeaders:
    """Additional tests for security headers."""

    def test_all_security_headers(self, client):
        """Test all security headers are present."""
        response = client.get("/health")
        headers = response.headers

        # Check all security headers
        assert "x-content-type-options" in headers
        assert headers["x-content-type-options"] == "nosniff"

        assert "x-frame-options" in headers
        assert headers["x-frame-options"] == "DENY"

        assert "x-xss-protection" in headers
        assert headers["x-xss-protection"] == "1; mode=block"

    def test_security_headers_on_all_endpoints(self, client):
        """Test security headers on different endpoints."""
        endpoints = ["/health", "/version", "/"]

        for endpoint in endpoints:
            response = client.get(endpoint)
            assert "x-content-type-options" in response.headers


class TestStreamingEndpoint:
    """Tests for streaming annotation endpoint."""

    def test_stream_endpoint_returns_sse(self, client):
        """Test that streaming endpoint returns SSE format."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        # Note: streaming tests are limited without async test support
        # This verifies the endpoint exists and responds with authentication
        response = client.post("/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS)
        # May be 503 if workflow not initialized, or 200 with streaming
        assert response.status_code in [200, 503]

    def test_stream_endpoint_requires_auth(self, client):
        """Test that streaming endpoint requires authentication."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        response = client.post("/annotate/stream", json=request_data)
        assert response.status_code == 401

    def test_stream_endpoint_accepts_model_override_headers(self, client):
        """Test that streaming endpoint accepts model/provider override headers."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-OpenRouter-Model": "anthropic/claude-haiku-4.5",
            "X-OpenRouter-Provider": "anthropic",
        }
        response = client.post("/annotate/stream", json=request_data, headers=headers)
        # 503 expected without workflow initialized, but should not be 400 for bad headers
        assert response.status_code in [200, 503]

    def test_stream_endpoint_accepts_temperature_header(self, client):
        """Test that streaming endpoint accepts temperature header."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-OpenRouter-Temperature": "0.5",
        }
        response = client.post("/annotate/stream", json=request_data, headers=headers)
        assert response.status_code in [200, 503]

    def test_stream_endpoint_handles_invalid_temperature_gracefully(self, client):
        """Test that streaming endpoint handles invalid temperature header."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-OpenRouter-Temperature": "invalid",
        }
        # Should not fail, just ignore invalid temperature
        response = client.post("/annotate/stream", json=request_data, headers=headers)
        assert response.status_code in [200, 503]

    def test_stream_endpoint_byok_mode_requires_key(self, client):
        """Test that BYOK mode streaming requires OpenRouter key."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        # Provide a valid BYOK key header pattern but with an invalid key
        # This should trigger BYOK mode check
        headers = {"X-OpenRouter-Key": "sk-or-v1-test"}
        response = client.post("/annotate/stream", json=request_data, headers=headers)
        # Should accept BYOK mode (503 because workflow can't be created with fake key)
        assert response.status_code in [401, 500, 503]

    def test_stream_endpoint_returns_sse_content_type(self, client):
        """Test that streaming endpoint returns SSE content type when successful."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        response = client.post("/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS)
        if response.status_code == 200:
            assert response.headers.get("content-type") == "text/event-stream; charset=utf-8"

    def test_stream_endpoint_with_user_id_header(self, client):
        """Test that streaming endpoint accepts user ID header."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-User-Id": "frontend-test-0.6.6",
        }
        response = client.post("/annotate/stream", json=request_data, headers=headers)
        assert response.status_code in [200, 503]

    def test_stream_endpoint_with_eval_model_headers(self, client):
        """Test that streaming endpoint accepts eval model headers."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-OpenRouter-Eval-Model": "qwen/qwen3-235b-a22b-2507",
            "X-OpenRouter-Eval-Provider": "Cerebras",
        }
        response = client.post("/annotate/stream", json=request_data, headers=headers)
        assert response.status_code in [200, 503]

    def test_stream_endpoint_with_assessment_flag(self, client):
        """Test that streaming endpoint accepts run_assessment flag."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
            "run_assessment": True,
        }
        response = client.post("/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS)
        assert response.status_code in [200, 503]

    def test_stream_endpoint_with_max_validation_attempts(self, client):
        """Test that streaming endpoint accepts max_validation_attempts."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
            "max_validation_attempts": 5,
        }
        response = client.post("/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS)
        assert response.status_code in [200, 503]


class TestStreamingWithMockedWorkflow:
    """Tests for streaming endpoint with mocked workflow."""

    @pytest.fixture
    def client_with_workflow(self):
        """Create a test client with a mocked workflow."""
        original_env = {}
        for key in ["REQUIRE_API_AUTH", "API_KEYS", "OPENROUTER_API_KEY"]:
            if key in os.environ:
                original_env[key] = os.environ[key]

        os.environ["REQUIRE_API_AUTH"] = "true"
        os.environ["API_KEYS"] = "test-api-key-for-unit-tests"
        os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"

        from src.api import security

        importlib.reload(security)

        # Create mock workflow
        mock_workflow = MagicMock()
        mock_graph = MagicMock()

        # Create async generator for streaming events
        async def mock_stream_events(*args, **kwargs):
            # Simulate node events
            yield {"event": "on_chain_start", "name": "annotate", "data": {}}
            yield {
                "event": "on_chain_end",
                "name": "annotate",
                "data": {"output": {"current_annotation": "Sensory-event, Visual"}},
            }
            yield {"event": "on_chain_start", "name": "validate", "data": {}}
            yield {
                "event": "on_chain_end",
                "name": "validate",
                "data": {"output": {"is_valid": True, "validation_errors": []}},
            }
            yield {"event": "on_chain_start", "name": "evaluate", "data": {}}
            yield {
                "event": "on_chain_end",
                "name": "evaluate",
                "data": {"output": {"is_faithful": True, "is_complete": True}},
            }

        mock_graph.astream_events = mock_stream_events
        mock_workflow.graph = mock_graph

        # Patch the workflow in main module
        with patch("src.api.main.workflow", mock_workflow):
            from src.api.main import app

            yield TestClient(app, raise_server_exceptions=False)

        # Restore original values
        for key in ["REQUIRE_API_AUTH", "API_KEYS", "OPENROUTER_API_KEY"]:
            if key in original_env:
                os.environ[key] = original_env[key]
            elif key in os.environ:
                del os.environ[key]

        importlib.reload(security)

    def test_stream_returns_progress_events(self, client_with_workflow):
        """Test that streaming returns progress events."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        response = client_with_workflow.post(
            "/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS
        )
        # Should get 200 with mock workflow
        assert response.status_code == 200
        assert "text/event-stream" in response.headers.get("content-type", "")

    def test_stream_content_has_events(self, client_with_workflow):
        """Test that streaming response contains SSE events."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        response = client_with_workflow.post(
            "/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS
        )
        content = response.text
        # Should contain event markers
        assert "event:" in content or response.status_code == 503

    def test_stream_has_safari_padding_comment(self, client_with_workflow):
        """SSE stream should start with padding comment for Safari compatibility."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        response = client_with_workflow.post(
            "/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS
        )
        if response.status_code == 200:
            # Stream should start with the SSE comment
            assert response.text.startswith(": stream opened")

    def test_stream_has_nosniff_header(self, client_with_workflow):
        """SSE streaming response should include X-Content-Type-Options: nosniff."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        response = client_with_workflow.post(
            "/annotate/stream", json=request_data, headers=TEST_AUTH_HEADERS
        )
        if response.status_code == 200:
            assert response.headers.get("x-content-type-options") == "nosniff"


class TestModelOverrideWithEnv:
    """Tests for model override with environment variables set."""

    @pytest.fixture
    def client_with_env(self):
        """Create a test client with OPENROUTER_API_KEY set."""
        original_env = {}
        for key in ["REQUIRE_API_AUTH", "API_KEYS", "OPENROUTER_API_KEY"]:
            if key in os.environ:
                original_env[key] = os.environ[key]

        os.environ["REQUIRE_API_AUTH"] = "true"
        os.environ["API_KEYS"] = "test-api-key-for-unit-tests"
        os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"

        from src.api import security

        importlib.reload(security)
        from src.api.main import app

        yield TestClient(app, raise_server_exceptions=False)

        # Restore original values
        for key in ["REQUIRE_API_AUTH", "API_KEYS", "OPENROUTER_API_KEY"]:
            if key in original_env:
                os.environ[key] = original_env[key]
            elif key in os.environ:
                del os.environ[key]

        importlib.reload(security)

    def test_annotate_with_model_override(self, client_with_env):
        """Test annotate endpoint with model override headers."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-OpenRouter-Model": "anthropic/claude-haiku-4.5",
            "X-OpenRouter-Provider": "anthropic",
        }
        response = client_with_env.post("/annotate", json=request_data, headers=headers)
        # Will fail to create workflow with fake key, but tests the code path
        assert response.status_code in [200, 500, 503]

    def test_stream_with_model_override(self, client_with_env):
        """Test streaming endpoint with model override headers."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-OpenRouter-Model": "anthropic/claude-haiku-4.5",
            "X-OpenRouter-Provider": "anthropic",
        }
        response = client_with_env.post("/annotate/stream", json=request_data, headers=headers)
        # Will fail to create workflow with fake key, but tests the code path
        assert response.status_code in [200, 500, 503]

    def test_stream_with_all_headers(self, client_with_env):
        """Test streaming endpoint with all override headers."""
        request_data = {
            "description": "A red circle appears",
            "schema_version": "8.3.0",
            "run_assessment": True,
            "max_validation_attempts": 5,
        }
        headers = {
            **TEST_AUTH_HEADERS,
            "X-OpenRouter-Model": "anthropic/claude-haiku-4.5",
            "X-OpenRouter-Provider": "anthropic",
            "X-OpenRouter-Temperature": "0.5",
            "X-OpenRouter-Eval-Model": "qwen/qwen3-235b-a22b-2507",
            "X-OpenRouter-Eval-Provider": "Cerebras",
            "X-User-Id": "test-user-123",
        }
        response = client_with_env.post("/annotate/stream", json=request_data, headers=headers)
        assert response.status_code in [200, 500, 503]


class TestVersionEndpointExtended:
    """Extended tests for version endpoint."""

    def test_version_includes_commit(self, client):
        """Test version endpoint includes commit hash."""
        response = client.get("/version")
        assert response.status_code == 200
        data = response.json()
        assert "version" in data
        assert "commit" in data


class TestUserIDDerivation:
    """Tests for user ID derivation from API keys."""

    def test_derive_user_id(self):
        """Test that user ID is derived consistently from API key."""
        from src.api.main import _derive_user_id

        api_key = "sk-or-test-key-12345"
        user_id = _derive_user_id(api_key)

        # Should be 16 hex characters
        assert len(user_id) == 16
        assert all(c in "0123456789abcdef" for c in user_id)

    def test_derive_user_id_consistency(self):
        """Test that same API key produces same user ID."""
        from src.api.main import _derive_user_id

        api_key = "sk-or-test-key-12345"
        user_id1 = _derive_user_id(api_key)
        user_id2 = _derive_user_id(api_key)

        assert user_id1 == user_id2

    def test_derive_user_id_uniqueness(self):
        """Test that different API keys produce different user IDs."""
        from src.api.main import _derive_user_id

        user_id1 = _derive_user_id("key1")
        user_id2 = _derive_user_id("key2")

        assert user_id1 != user_id2


class TestTelemetryEnabledField:
    """Tests for telemetry_enabled field in request models."""

    def test_annotation_request_telemetry_default_true(self):
        """Test AnnotationRequest has telemetry_enabled=True by default."""
        from src.api.models import AnnotationRequest

        request = AnnotationRequest(description="Test description")
        assert request.telemetry_enabled is True

    def test_annotation_request_telemetry_can_be_disabled(self):
        """Test AnnotationRequest telemetry_enabled can be set to False."""
        from src.api.models import AnnotationRequest

        request = AnnotationRequest(description="Test description", telemetry_enabled=False)
        assert request.telemetry_enabled is False

    def test_image_annotation_request_telemetry_default_true(self):
        """Test ImageAnnotationRequest has telemetry_enabled=True by default."""
        from src.api.models import ImageAnnotationRequest

        request = ImageAnnotationRequest(image="base64data")
        assert request.telemetry_enabled is True

    def test_image_annotation_request_telemetry_can_be_disabled(self):
        """Test ImageAnnotationRequest telemetry_enabled can be set to False."""
        from src.api.models import ImageAnnotationRequest

        request = ImageAnnotationRequest(image="base64data", telemetry_enabled=False)
        assert request.telemetry_enabled is False

    def test_annotate_endpoint_accepts_telemetry_enabled(self, client):
        """Test annotate endpoint accepts telemetry_enabled field."""
        request_data = {
            "description": "A red circle appears on the screen",
            "schema_version": "8.3.0",
            "telemetry_enabled": False,
        }
        response = client.post("/annotate", json=request_data, headers=TEST_AUTH_HEADERS)
        # May be 503 if workflow not initialized, or 200 if it is
        # But should NOT be 422 (validation error)
        assert response.status_code in [200, 503]

    def test_image_annotate_endpoint_accepts_telemetry_enabled(self, client):
        """Test image annotation endpoint accepts telemetry_enabled field."""
        request_data = {
            "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
            "telemetry_enabled": False,
        }
        response = client.post("/annotate-from-image", json=request_data, headers=TEST_AUTH_HEADERS)
        # May be 503 if vision agent not initialized, or 200 if it is
        # But should NOT be 422 (validation error)
        assert response.status_code in [200, 503]


class TestTelemetryCollectorIntegration:
    """Tests for telemetry collector integration in API."""

    def test_telemetry_collector_initialization(self):
        """Test that telemetry_collector global is defined."""
        from src.api import main

        # telemetry_collector should be defined (may be None before lifespan)
        assert hasattr(main, "telemetry_collector")

    def test_telemetry_imports_available(self):
        """Test that telemetry imports are available in main module."""
        from src.api.main import LocalFileStorage, TelemetryCollector, TelemetryEvent

        # Verify classes are importable
        assert LocalFileStorage is not None
        assert TelemetryCollector is not None
        assert TelemetryEvent is not None

    def test_telemetry_event_creation(self):
        """Test creating a telemetry event with API-like data."""
        from src.telemetry import TelemetryEvent

        event = TelemetryEvent.create(
            description="Test description from API",
            schema_version="8.3.0",
            hed_string="Sensory-event, Visual-presentation",
            iterations=2,
            validation_errors=[],
            model="mistralai/mistral-small-3.2-24b-instruct",
            provider="mistral",
            temperature=0.1,
            latency_ms=1500,
            source="api",
        )

        # TelemetryEvent uses nested models
        assert event.input.description == "Test description from API"
        assert event.input.schema_version == "8.3.0"
        assert event.output.hed_string == "Sensory-event, Visual-presentation"
        assert event.output.iterations == 2
        assert event.performance.latency_ms == 1500
        assert event.source == "api"

    def test_telemetry_event_image_source(self):
        """Test creating a telemetry event with api-image source."""
        from src.telemetry import TelemetryEvent

        event = TelemetryEvent.create(
            description="Generated image description",
            schema_version="8.4.0",
            hed_string="Visual-presentation",
            iterations=1,
            validation_errors=[],
            model="openai/gpt-4o",
            provider="deepinfra/fp8",
            temperature=0.3,
            latency_ms=3000,
            source="api-image",
        )

        assert event.source == "api-image"
        assert event.model.provider == "deepinfra/fp8"
