"""Tests for the ihyee-mcp formatter module."""
from __future__ import annotations

from ihyee.models import (
    ContentItem,
    DocumentContent,
    ExtractedLink,
    FetchResponse,
    ImageContent,
    ResponseMeta,
    SearchResponse,
    TextContent as IhyeeTextContent,
)

from ihyee_mcp.formatter import (
    _format_content_item,
    _format_links,
    format_fetch_response,
    format_search_response,
)


# ---------------------------------------------------------------------------
# Fixtures / helpers
# ---------------------------------------------------------------------------

def _make_text_content(
    summary: str | None = "A test summary.",
    full_text: str | None = "Full text content here.",
    author: str = "Test Author",
    date_published: str = "2025-01-15",
    links: list[ExtractedLink] | None = None,
    error: str | None = None,
) -> IhyeeTextContent:
    return IhyeeTextContent(
        summary=summary,
        full_text=full_text,
        author=author,
        date_published=date_published,
        links=links or [],
        error=error,
    )


def _make_content_item(
    url: str = "https://example.com",
    text: IhyeeTextContent | None = None,
    item_type: str = "text",
) -> ContentItem:
    return ContentItem(
        type=item_type,
        url=url,
        text=text or _make_text_content(),
    )


def _make_search_response(
    query: str = "test query",
    items: list[ContentItem] | None = None,
    search_time_ms: int = 1234,
) -> SearchResponse:
    content = items or [_make_content_item()]
    return SearchResponse(
        query=query,
        results_count=len(content),
        content=content,
        meta=ResponseMeta(
            search_time_ms=search_time_ms,
            pages_fetched=len(content),
            content_mode="both",
        ),
    )


def _make_fetch_response(
    items: list[ContentItem] | None = None,
) -> FetchResponse:
    content = items or [_make_content_item()]
    return FetchResponse(
        content=content,
        meta=ResponseMeta(
            pages_fetched=len(content),
            content_mode="both",
        ),
    )


# ---------------------------------------------------------------------------
# Tests: _format_links
# ---------------------------------------------------------------------------

class TestFormatLinks:
    def test_no_text(self) -> None:
        item = ContentItem(type="text", url="https://example.com", text=None)
        assert _format_links(item) == ""

    def test_no_links(self) -> None:
        item = _make_content_item(text=_make_text_content(links=[]))
        assert _format_links(item) == ""

    def test_with_links(self) -> None:
        links = [
            ExtractedLink(url="https://a.com", text="Link A", context=""),
            ExtractedLink(url="https://b.com", text="Link B", context="some context"),
        ]
        item = _make_content_item(text=_make_text_content(links=links))
        result = _format_links(item)
        assert "**Links:**" in result
        assert "Link A: https://a.com" in result
        assert "Link B: https://b.com" in result

    def test_link_with_no_text_falls_back_to_context(self) -> None:
        links = [
            ExtractedLink(url="https://c.com", text="", context="Context text"),
        ]
        item = _make_content_item(text=_make_text_content(links=links))
        result = _format_links(item)
        assert "Context text: https://c.com" in result

    def test_link_with_no_text_or_context_uses_default(self) -> None:
        links = [
            ExtractedLink(url="https://d.com", text="", context=""),
        ]
        item = _make_content_item(text=_make_text_content(links=links))
        result = _format_links(item)
        assert "Link: https://d.com" in result

    def test_caps_at_10_links(self) -> None:
        links = [
            ExtractedLink(url=f"https://link{i}.com", text=f"Link {i}", context="")
            for i in range(15)
        ]
        item = _make_content_item(text=_make_text_content(links=links))
        result = _format_links(item)
        assert "Link 9" in result
        assert "Link 10" not in result


# ---------------------------------------------------------------------------
# Tests: _format_content_item
# ---------------------------------------------------------------------------

class TestFormatContentItem:
    def test_with_index_and_url(self) -> None:
        item = _make_content_item(url="https://example.com")
        result = _format_content_item(item, index=1)
        assert "### 1. https://example.com" in result

    def test_without_index(self) -> None:
        item = _make_content_item(url="https://example.com")
        result = _format_content_item(item)
        assert "### https://example.com" in result

    def test_displays_author_and_date(self) -> None:
        text = _make_text_content(author="Jane Doe", date_published="2025-03-01")
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "**Author:** Jane Doe" in result
        assert "**Published:** 2025-03-01" in result

    def test_hides_unknown_author(self) -> None:
        text = _make_text_content(author="Unknown", date_published="Unknown")
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "Author" not in result
        assert "Published" not in result

    def test_displays_summary(self) -> None:
        text = _make_text_content(summary="This is a great summary.")
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "This is a great summary." in result

    def test_displays_full_text_when_no_summary(self) -> None:
        text = _make_text_content(summary=None, full_text="Full text only content.")
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "Full text only content." in result
        assert "**Full text:**" not in result

    def test_displays_full_text_under_heading_when_summary_exists(self) -> None:
        text = _make_text_content(summary="Summary here.", full_text="Full text here.")
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "Summary here." in result
        assert "**Full text:**" in result
        assert "Full text here." in result

    def test_truncates_long_full_text_with_summary(self) -> None:
        long_text = "x" * 4000
        text = _make_text_content(summary="Short summary.", full_text=long_text)
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "[... truncated]" in result
        assert len(result) < 4000  # Should be truncated

    def test_truncates_long_full_text_without_summary(self) -> None:
        long_text = "y" * 6000
        text = _make_text_content(summary=None, full_text=long_text)
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "[... truncated]" in result

    def test_error_content(self) -> None:
        text = _make_text_content(error="Connection timeout", summary=None, full_text=None)
        item = _make_content_item(text=text)
        result = _format_content_item(item, index=1)
        assert "**Error:** Connection timeout" in result

    def test_image_content(self) -> None:
        item = ContentItem(
            type="image",
            url="https://example.com/page",
            text=None,
            image_url=ImageContent(url="https://example.com/img.png", alt="A cat"),
        )
        result = _format_content_item(item, index=1)
        assert "**Image:** https://example.com/img.png" in result
        assert "**Alt text:** A cat" in result

    def test_document_content(self) -> None:
        item = ContentItem(
            type="document",
            url="https://example.com/doc",
            text=None,
            document=DocumentContent(
                s3_url="s3://bucket/doc.pdf",
                original_url="https://example.com/doc.pdf",
                content_type="application/pdf",
                size_bytes=1_048_576,
            ),
        )
        result = _format_content_item(item, index=1)
        assert "**Document:** https://example.com/doc.pdf" in result
        assert "**Type:** application/pdf" in result
        assert "1,048,576 bytes" in result


# ---------------------------------------------------------------------------
# Tests: format_search_response
# ---------------------------------------------------------------------------

class TestFormatSearchResponse:
    def test_header_includes_query(self) -> None:
        resp = _make_search_response(query="transformer architecture")
        result = format_search_response(resp)
        assert '## Search Results for "transformer architecture"' in result

    def test_includes_result_count(self) -> None:
        items = [_make_content_item(url=f"https://example.com/{i}") for i in range(3)]
        resp = _make_search_response(items=items)
        result = format_search_response(resp)
        assert "*3 results found*" in result

    def test_includes_meta_info(self) -> None:
        resp = _make_search_response(search_time_ms=500)
        result = format_search_response(resp)
        assert "Search time: 500ms" in result
        assert "Pages fetched:" in result

    def test_numbers_results(self) -> None:
        items = [
            _make_content_item(url="https://a.com"),
            _make_content_item(url="https://b.com"),
        ]
        resp = _make_search_response(items=items)
        result = format_search_response(resp)
        assert "### 1. https://a.com" in result
        assert "### 2. https://b.com" in result

    def test_degraded_note(self) -> None:
        resp = _make_search_response()
        resp.meta.degraded = True
        result = format_search_response(resp)
        assert "degraded" in result.lower()

    def test_render_skipped_note(self) -> None:
        resp = _make_search_response()
        resp.meta.render_skipped = "quota exceeded"
        result = format_search_response(resp)
        assert "quota exceeded" in result


# ---------------------------------------------------------------------------
# Tests: format_fetch_response
# ---------------------------------------------------------------------------

class TestFormatFetchResponse:
    def test_default_label(self) -> None:
        resp = _make_fetch_response()
        result = format_fetch_response(resp)
        assert "## Fetched Content" in result

    def test_custom_label(self) -> None:
        resp = _make_fetch_response()
        result = format_fetch_response(resp, label="Rendered Page Content")
        assert "## Rendered Page Content" in result

    def test_includes_page_count(self) -> None:
        items = [_make_content_item(url=f"https://x.com/{i}") for i in range(2)]
        resp = _make_fetch_response(items=items)
        result = format_fetch_response(resp)
        assert "*2 page(s) processed*" in result

    def test_single_url(self) -> None:
        resp = _make_fetch_response()
        result = format_fetch_response(resp)
        assert "### 1. https://example.com" in result
        assert "A test summary." in result

    def test_includes_meta(self) -> None:
        resp = _make_fetch_response()
        resp.meta.pages_rendered = 1
        result = format_fetch_response(resp)
        assert "Pages rendered: 1" in result
