from __future__ import annotations

import json

import httpx

from firecrawl_client.client import FirecrawlClient
from firecrawl_client.models import MapResult


def _make_client(transport: httpx.MockTransport) -> FirecrawlClient:
    return FirecrawlClient(
        api_url="https://crawl.example.test",
        api_key="fc-test",
        transport=transport,
    )


def test_map_posts_v2_endpoint_with_url_and_limit():
    captured: dict = {}

    def handler(request: httpx.Request) -> httpx.Response:
        captured["url"] = str(request.url)
        captured["body"] = json.loads(request.content)
        return httpx.Response(200, json={
            "success": True,
            "links": ["https://roma.com/", "https://roma.com/about", "https://roma.com/team"],
        })

    transport = httpx.MockTransport(handler)
    client = _make_client(transport)
    result = client.map("roma.com", limit=50)

    assert captured["url"] == "https://crawl.example.test/v2/map"
    assert captured["body"]["url"] == "https://roma.com"
    assert captured["body"]["limit"] == 50
    assert isinstance(result, MapResult)
    assert result.domain == "roma.com"
    assert "https://roma.com/team" in result.urls
    assert len(result.urls) == 3


def test_map_with_search_term_in_body():
    captured: dict = {}

    def handler(request: httpx.Request) -> httpx.Response:
        captured["body"] = json.loads(request.content)
        return httpx.Response(200, json={"success": True, "links": []})

    transport = httpx.MockTransport(handler)
    client = _make_client(transport)
    client.map("roma.com", search_term="team")
    assert captured["body"]["search"] == "team"


def test_map_returns_empty_urls_on_empty_response():
    def handler(_request: httpx.Request) -> httpx.Response:
        return httpx.Response(200, json={"success": True, "links": []})

    transport = httpx.MockTransport(handler)
    client = _make_client(transport)
    result = client.map("roma.com")
    assert result.urls == []


def test_map_unwraps_dict_shaped_links():
    """Firecrawl /v2/map returns links as [{"url": "..."}, ...] for some
    sites (e.g., mejuri.com). The client must normalize to plain strings."""
    def handler(_request: httpx.Request) -> httpx.Response:
        return httpx.Response(200, json={
            "success": True,
            "links": [
                {"url": "https://roma.com/products/ring"},
                {"url": "https://roma.com/about", "title": "About"},
                {"url": "https://roma.com/team", "description": "The team"},
            ],
        })

    transport = httpx.MockTransport(handler)
    client = _make_client(transport)
    result = client.map("roma.com")
    assert result.urls == [
        "https://roma.com/products/ring",
        "https://roma.com/about",
        "https://roma.com/team",
    ]


def test_map_handles_mixed_string_and_dict_links():
    """Belt-and-suspenders: if a response mixes strings and dicts, both work."""
    def handler(_request: httpx.Request) -> httpx.Response:
        return httpx.Response(200, json={
            "success": True,
            "links": [
                "https://roma.com/a",
                {"url": "https://roma.com/b"},
                {"no_url_field": "ignored"},  # malformed entry — drop silently
                "https://roma.com/c",
            ],
        })

    transport = httpx.MockTransport(handler)
    client = _make_client(transport)
    result = client.map("roma.com")
    assert result.urls == ["https://roma.com/a", "https://roma.com/b", "https://roma.com/c"]
