from types import SimpleNamespace

import pytest

from app.shared.clients.openai_client import UnifiedOpenAIClient


class FakeAnalyticsService:
    enabled = True

    def __init__(self):
        self.calls = []

    async def log_usage(self, **kwargs):
        self.calls.append(kwargs)

    async def close(self):
        return None


@pytest.mark.anyio("asyncio")
async def test_json_completion_logs_analytics_and_sanitizes_images():
    client = UnifiedOpenAIClient()
    analytics_service = FakeAnalyticsService()
    client.set_analytics_service(analytics_service)

    response = SimpleNamespace(
        choices=[
            SimpleNamespace(
                message=SimpleNamespace(content='{"ok": true}'),
                finish_reason="stop",
            )
        ],
        usage=SimpleNamespace(
            prompt_tokens=1240,
            completion_tokens=356,
            total_tokens=1596,
            prompt_tokens_details=SimpleNamespace(cached_tokens=180),
            completion_tokens_details=SimpleNamespace(reasoning_tokens=44),
        ),
        model="gpt-4o-mini-2024-07-18",
    )

    class FakeCompletions:
        async def create(self, **kwargs):
            return response

    class FakeChat:
        completions = FakeCompletions()

    class FakeOpenAIClient:
        chat = FakeChat()

        async def close(self):
            return None

    client.get_client = lambda api_key: FakeOpenAIClient()

    result, metrics = await client.json_completion(
        api_key="test-key",
        model="gpt-4o-mini",
        messages=[{
            "role": "user",
            "content": [
                {"type": "text", "text": "Generate short promo text"},
                {"type": "image_url", "image_url": {"url": "data:image/png;base64,AAAA"}},
            ],
        }],
        operation_id="menu_extraction",
        service="menu_extraction",
        max_tokens=500,
        analytics_context={
            "city": "sofia",
            "zavedenia_id": 3054,
            "data_input": {"source_language": "bg"},
        },
    )

    assert result == {"ok": True}
    assert metrics["input_tokens"] == 1240
    assert len(analytics_service.calls) == 1

    payload = analytics_service.calls[0]
    assert payload["service"] == "openai"
    assert payload["city"] == "sofia"
    assert payload["zavedenia_id"] == 3054
    assert payload["tokens_input"] == {
        "prompt_tokens": 1240,
        "cached_tokens": 180,
        "total_tokens": 1240,
    }
    assert payload["tokens_output"] == {
        "completion_tokens": 356,
        "reasoning_tokens": 44,
        "total_tokens": 356,
    }
    assert payload["data_input"]["app_service"] == "menu_extraction"
    assert payload["data_input"]["source_language"] == "bg"
    assert payload["data_input"]["messages"][0]["content"][1]["image_url"]["url"] == "[omitted_data_url]"
    assert payload["data_output"]["content"] == '{"ok": true}'


@pytest.mark.anyio("asyncio")
async def test_json_completion_ignores_analytics_failures():
    client = UnifiedOpenAIClient()

    class FailingAnalyticsService:
        enabled = True

        async def log_usage(self, **kwargs):
            raise RuntimeError("analytics down")

        async def close(self):
            return None

    client.set_analytics_service(FailingAnalyticsService())

    response = SimpleNamespace(
        choices=[SimpleNamespace(message=SimpleNamespace(content='{"ok": true}'), finish_reason="stop")],
        usage=SimpleNamespace(
            prompt_tokens=1,
            completion_tokens=1,
            total_tokens=2,
            prompt_tokens_details=None,
            completion_tokens_details=None,
        ),
        model="gpt-4o-mini-2024-07-18",
    )

    class FakeCompletions:
        async def create(self, **kwargs):
            return response

    class FakeChat:
        completions = FakeCompletions()

    class FakeOpenAIClient:
        chat = FakeChat()

        async def close(self):
            return None

    client.get_client = lambda api_key: FakeOpenAIClient()

    result, metrics = await client.json_completion(
        api_key="test-key",
        model="gpt-4o-mini",
        prompt="hello",
        operation_id="translation",
        service="translation",
    )

    assert result == {"ok": True}
    assert metrics["total_tokens"] == 2
