"""Tests for Wix MCP handler."""

import json
from unittest.mock import patch

from nlweb_platform_handlers.wix import WixMCPHandler


class TestWixMCPHandler:
    """Tests for WixMCPHandler."""

    def setup_method(self):
        with patch("nlweb_core.handler.set_request_id", return_value="test-req-id"):
            self.handler = WixMCPHandler()

    # ── URL helpers ──────────────────────────────────────────────────────

    def test_make_absolute_url_already_absolute(self):
        assert (
            self.handler._make_absolute_url("https://example.com/page", "site.com")
            == "https://example.com/page"
        )

    def test_make_absolute_url_relative_with_slash(self):
        assert (
            self.handler._make_absolute_url("/products/item", "site.com")
            == "https://site.com/products/item"
        )

    def test_make_absolute_url_relative_no_slash(self):
        assert (
            self.handler._make_absolute_url("products/item", "site.com")
            == "https://site.com/products/item"
        )

    def test_make_absolute_url_protocol_relative(self):
        assert (
            self.handler._make_absolute_url("//cdn.example.com/img.jpg", "site.com")
            == "https://cdn.example.com/img.jpg"
        )

    def test_make_absolute_url_none(self):
        assert self.handler._make_absolute_url(None, "site.com") is None

    # ── Wix media ID conversion ──────────────────────────────────────────

    def test_wix_media_to_url_media_id(self):
        result = self.handler._wix_media_to_url("38036e_abc~mv2.jpg")
        assert result == "https://static.wixstatic.com/media/38036e_abc~mv2.jpg"

    def test_wix_media_to_url_already_url(self):
        result = self.handler._wix_media_to_url("https://example.com/img.jpg")
        assert result == "https://example.com/img.jpg"

    def test_wix_media_to_url_none(self):
        assert self.handler._wix_media_to_url(None) is None

    # ── Schema type detection ────────────────────────────────────────────

    def test_item_to_schema_detects_product(self):
        item = {"name": "Widget", "price": 9.99, "url": "/products/widget"}
        result = self.handler._item_to_schema(item, "site.com")
        assert result["@type"] == "Product"
        assert result["name"] == "Widget"
        assert result["offers"]["price"] == 9.99

    def test_item_to_schema_detects_article(self):
        item = {
            "title": "Blog Post",
            "body": "Some content...",
            "publishedDate": "2025-01-01",
        }
        result = self.handler._item_to_schema(item, "site.com")
        assert result["@type"] == "Article"
        assert result["headline"] == "Blog Post"
        assert result["articleBody"] == "Some content..."

    def test_item_to_schema_defaults_to_webpage(self):
        item = {"title": "About Us", "description": "Our company"}
        result = self.handler._item_to_schema(item, "site.com")
        assert result["@type"] == "WebPage"
        assert result["name"] == "About Us"

    # ── Image from Wix media fields ──────────────────────────────────────

    def test_product_with_wix_media_img(self):
        item = {"name": "Widget", "price": 5, "img": "abc123~mv2.jpg"}
        result = self.handler._product_to_schema(item, "site.com")
        assert result["image"] == "https://static.wixstatic.com/media/abc123~mv2.jpg"

    def test_article_with_wix_media_images_array(self):
        item = {
            "title": "Post",
            "body": "text",
            "images": ["img1~mv2.jpg", "img2~mv2.jpg"],
        }
        result = self.handler._article_to_schema(item, "site.com")
        assert result["image"] == "https://static.wixstatic.com/media/img1~mv2.jpg"

    # ── MCP response parsing ─────────────────────────────────────────────

    def test_parse_mcp_response_content_array(self):
        products = {"products": [{"name": "Item A", "price": 10, "url": "/item-a"}]}
        mcp_response = {
            "result": {
                "content": [
                    {"type": "text", "text": json.dumps(products)},
                ]
            }
        }
        result = self.handler._parse_mcp_response(
            mcp_response, "site.wixsite.com/store", "SearchSiteApiDocs"
        )
        assert len(result) == 1
        assert result[0].site == "site.wixsite.com/store"

    def test_parse_mcp_response_with_wrapper_prefix(self):
        """Test 'Site search tool returned: {...}' wrapper is stripped."""
        data = {"results": [{"title": "Page", "url": "/page"}]}
        mcp_response = {
            "result": {
                "content": [
                    {
                        "type": "text",
                        "text": f"Site search tool returned: {json.dumps(data)}",
                    },
                ]
            }
        }
        result = self.handler._parse_mcp_response(
            mcp_response, "site.wixsite.com/store", "SearchInSite"
        )
        assert len(result) == 1

    def test_parse_mcp_response_nested_result(self):
        """Test nested 'result' key is unwrapped."""
        data = {"result": {"items": [{"title": "Nested", "url": "/nested"}]}}
        mcp_response = {
            "result": {
                "content": [
                    {"type": "text", "text": json.dumps(data)},
                ]
            }
        }
        result = self.handler._parse_mcp_response(
            mcp_response, "site.com", "SearchInSite"
        )
        assert len(result) == 1

    def test_parse_mcp_response_plain_text_fallback(self):
        """Test plain text content creates a WebPage item."""
        mcp_response = {
            "result": {
                "content": [
                    {"type": "text", "text": "This is not JSON, just text."},
                ]
            }
        }
        result = self.handler._parse_mcp_response(
            mcp_response, "site.com", "SearchInSite"
        )
        assert len(result) == 1
        schema = result[0].schema_object[0]
        assert schema["@type"] == "WebPage"
        assert "This is not JSON" in schema["text"]

    def test_parse_mcp_response_error_flag(self):
        """Test isError response returns empty list."""
        mcp_response = {"result": {"isError": True}}
        result = self.handler._parse_mcp_response(
            mcp_response, "site.com", "SearchInSite"
        )
        assert result == []

    # ── Retrieve items ───────────────────────────────────────────────────

    async def test_retrieve_items_no_site(self):
        result = await self.handler._retrieve_items("query", site=None, num_results=10)
        assert result == []

    def test_text_to_item_empty(self):
        assert self.handler._text_to_item("", "site.com") is None
        assert self.handler._text_to_item("   ", "site.com") is None

    def test_text_to_item_valid(self):
        item = self.handler._text_to_item("Some content here", "site.com")
        assert item is not None
        schema = item.schema_object[0]
        assert schema["@type"] == "WebPage"
        assert item.url == "https://site.com"

    def test_format_results_various_keys(self):
        """Test that format_results handles different Wix result keys."""
        for key in ["results", "items", "products", "documents", "pages"]:
            data = {key: [{"title": f"From {key}", "url": f"/{key}"}]}
            items = self.handler._format_results(data, "site.com")
            assert len(items) == 1, f"Failed for key: {key}"
