"""Integration tests for POST /api/search/build."""
from __future__ import annotations

import json
from unittest.mock import MagicMock, patch

import pytest
from fastapi.testclient import TestClient


@pytest.fixture
def client(tmp_path):
    """TestClient with a fresh DB and mocked LLMRouter/category cache."""
    import os
    os.environ["SNIPE_DB"] = str(tmp_path / "snipe.db")
    # Import app AFTER setting SNIPE_DB so the DB path is picked up
    from api.main import app
    return TestClient(app, raise_server_exceptions=False)


def _good_llm_response() -> str:
    return json.dumps({
        "base_query": "RTX 3080",
        "must_include_mode": "groups",
        "must_include": "rtx|geforce, 3080",
        "must_exclude": "mining",
        "max_price": 300.0,
        "min_price": None,
        "condition": ["used"],
        "category_id": "27386",
        "explanation": "Used RTX 3080 under $300.",
    })


def test_build_endpoint_success(client):
    with patch("api.main._get_query_translator") as mock_get_t:
        mock_t = MagicMock()
        from app.llm.query_translator import SearchParamsResponse
        mock_t.translate.return_value = SearchParamsResponse(
            base_query="RTX 3080",
            must_include_mode="groups",
            must_include="rtx|geforce, 3080",
            must_exclude="mining",
            max_price=300.0,
            min_price=None,
            condition=["used"],
            category_id="27386",
            explanation="Used RTX 3080 under $300.",
        )
        mock_get_t.return_value = mock_t
        resp = client.post(
            "/api/search/build",
            json={"natural_language": "used RTX 3080 under $300 no mining"},
        )
    assert resp.status_code == 200
    data = resp.json()
    assert data["base_query"] == "RTX 3080"
    assert data["explanation"] == "Used RTX 3080 under $300."


def test_build_endpoint_llm_unavailable(client):
    with patch("api.main._get_query_translator") as mock_get_t:
        mock_get_t.return_value = None  # no translator configured
        resp = client.post(
            "/api/search/build",
            json={"natural_language": "GPU"},
        )
    assert resp.status_code == 503


def test_build_endpoint_bad_json(client):
    with patch("api.main._get_query_translator") as mock_get_t:
        from app.llm.query_translator import QueryTranslatorError
        mock_t = MagicMock()
        mock_t.translate.side_effect = QueryTranslatorError("unparseable", raw="garbage output")
        mock_get_t.return_value = mock_t
        resp = client.post(
            "/api/search/build",
            json={"natural_language": "GPU"},
        )
    assert resp.status_code == 422
    assert "raw" in resp.json()["detail"]
