from unittest.mock import patch

import pytest

from app.core.prompts import chat_system_prompt
from app.services.chat.tools import TOOL_EXECUTORS, TOOL_SCHEMAS
from app.services.chat.tools_settings import FEATURE_TOOLS

ROW = {"product_key": "sku:BR-42", "name": "Blue Runner", "description": "A shoe",
       "image_url": None, "product_url": "https://s.com/p", "category": "shoes",
       "ctas": [{"type": "view", "label": "View details", "url": "https://s.com/p"}]}


def test_the_tool_is_registered_on_both_sides():
    names = {t["function"]["name"] for t in TOOL_SCHEMAS}
    assert "recommend_products" in names
    assert names == set(TOOL_EXECUTORS)


def test_the_switch_is_wired_to_the_tool():
    assert FEATURE_TOOLS["product_recommendation"] == "recommend_products"


def test_disabling_it_removes_it_from_the_prompt():
    on = chat_system_prompt()
    off = chat_system_prompt({"recommend_products"})
    assert "recommend_products" in on
    assert "recommend_products" not in off.split("You CANNOT recommend")[0]
    assert "<<<" not in off


@pytest.mark.asyncio
async def test_returns_only_rows_that_exist():
    from app.services.chat.tools import execute_recommend_products
    with patch("app.services.chat.tools.semantic_products", return_value=[ROW]):
        result = await execute_recommend_products(
            {"query": "running shoes"}, {"tenant_id": "org_x"})
    assert result["status"] == "found"
    assert result["products"][0]["name"] == "Blue Runner"
    assert "price" not in result["products"][0]


@pytest.mark.asyncio
async def test_an_empty_catalogue_says_so_rather_than_inventing():
    from app.services.chat.tools import execute_recommend_products
    with patch("app.services.chat.tools.semantic_products", return_value=[]), \
         patch("app.services.chat.tools.match_products", return_value=[]):
        result = await execute_recommend_products(
            {"query": "spaceships"}, {"tenant_id": "org_x"})
    assert result["status"] == "none"
    assert result["products"] == []


@pytest.mark.asyncio
async def test_products_reach_the_model_without_a_price_or_stock_level():
    """The model must not be able to quote a number we did not extract."""
    from app.services.chat.tools import execute_recommend_products
    with patch("app.services.chat.tools.semantic_products", return_value=[ROW]):
        result = await execute_recommend_products({"query": "x"}, {"tenant_id": "org_x"})
    card = result["products"][0]
    assert "price" not in card and "currency" not in card and "availability" not in card
