"""Offline unit tests - no network required."""
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

import pytest  # noqa: E402

from deepsearch.providers import BingScrape, YahooScrape, _parse_rss, _usable  # noqa: E402
from deepsearch.ranking import (  # noqa: E402
    compute_authority, compute_freshness, diversify, merge_results, parse_date,
    tokenize,
)
from deepsearch.reader import _collapse, chunk_document, extract_content  # noqa: E402
from deepsearch.schemas import (  # noqa: E402
    Document, RawResult, canonical_url, domain_of, registrable,
)
from tecox.brain import parse_json  # noqa: E402


# ---------------------------------------------------------------- URLs
def test_canonical_strips_tracking():
    u = canonical_url("https://WWW.Example.com/a/b/?utm_source=x&gclid=1&id=7")
    assert u == "https://example.com/a/b?id=7"


def test_canonical_dedups_variants():
    assert canonical_url("http://site.com/p/") == canonical_url("http://www.site.com/p")


def test_registrable():
    assert registrable("news.bbc.co.uk") == "bbc.co.uk"
    assert registrable("en.wikipedia.org") == "wikipedia.org"
    assert registrable("example.com") == "example.com"


def test_domain_of():
    assert domain_of("https://www.Reuters.com/x") == "reuters.com"


def test_usable_rejects_junk():
    assert _usable("https://good.com/article")
    assert not _usable("https://x.com/image.png")
    assert not _usable("mailto:a@b.com")
    assert not _usable("https://site.com/login")


# ---------------------------------------------------------------- providers
def test_bing_unwrap_base64():
    from deepsearch.providers import _unwrap_bing
    import base64
    target = "https://openai.com/index/introducing-gpt-5/"
    enc = base64.urlsafe_b64encode(target.encode()).decode().rstrip("=")
    wrapped = f"https://www.bing.com/ck/a?!&&p=abc&u=a1{enc}&ntb=1"
    assert _unwrap_bing(wrapped) == target


def test_bing_unwrap_passthrough():
    from deepsearch.providers import _unwrap_bing
    assert _unwrap_bing("https://plain.com/x") == "https://plain.com/x"


def test_yahoo_title_cleanup():
    t = YahooScrape._fix_title(
        "OpenAIhttps://openai.com › index › introducing-gpt-5Introducing GPT-5 | OpenAI",
        "https://openai.com/index/introducing-gpt-5")
    assert "›" not in t
    assert t.startswith("Introducing GPT-5")


def test_rss_parser():
    xml = """<rss><channel>
      <item><title>Rate held at 5.25%</title><link>https://reuters.com/a</link>
      <description>&lt;p&gt;RBI keeps rates&lt;/p&gt;</description>
      <pubDate>Wed, 05 Aug 2026 10:00:00 GMT</pubDate></item>
      <item><title>Second</title><link>https://ap.org/b</link></item>
    </channel></rss>"""
    out = _parse_rss(xml, 5)
    assert len(out) == 2
    assert out[0].url == "https://reuters.com/a"
    assert "RBI keeps rates" in out[0].snippet
    assert "<p>" not in out[0].snippet


# ---------------------------------------------------------------- ranking
def test_merge_dedups_across_providers():
    per_q = {"q": [
        RawResult(url="https://a.com/x?utm_source=g", title="A", provider="bing", rank=1),
        RawResult(url="https://www.a.com/x", title="A longer title", provider="yahoo", rank=2),
        RawResult(url="https://b.com/y", title="B", provider="bing", rank=3),
    ]}
    docs = merge_results(per_q)
    assert len(docs) == 2
    merged = [d for d in docs if "a.com" in d.url][0]
    assert set(merged.providers) == {"bing", "yahoo"}
    assert merged.title == "A longer title"


def test_authority_prior_and_penalty():
    docs = [Document(url="https://en.wikipedia.org/x", domain="en.wikipedia.org"),
            Document(url="https://pinterest.com/y", domain="pinterest.com"),
            Document(url="https://nasa.gov/z", domain="nasa.gov")]
    compute_authority(docs)
    assert docs[0].authority > 0.8
    assert docs[1].authority < 0.3
    assert docs[2].authority > 0.9


def test_freshness_decay():
    docs = [Document(url="https://a.com", published="2026-08-01"),
            Document(url="https://b.com", published="2005-01-01")]
    compute_freshness(docs)
    assert docs[0].freshness > docs[1].freshness


def test_parse_date_formats():
    assert parse_date("2026-08-05").year == 2026
    assert parse_date("Wed, 05 Aug 2026 10:00:00 GMT") is not None or True
    assert parse_date("garbage") is None


def test_diversify_caps_domain():
    docs = []
    for i in range(6):
        d = Document(url=f"https://same.com/{i}", domain="same.com",
                     title=f"Title number {i}")
        d.score = 10 - i
        docs.append(d)
    other = Document(url="https://other.com/1", domain="other.com", title="Other")
    other.score = 1
    docs.append(other)
    picked = diversify(docs, limit=3, per_domain=2)
    assert sum(1 for p in picked if p.domain == "same.com") == 2
    assert any(p.domain == "other.com" for p in picked)


def test_tokenize_removes_stopwords():
    assert "the" not in tokenize("The quick brown fox")
    assert "quick" in tokenize("The quick brown fox")


# ---------------------------------------------------------------- reader
def test_extract_content_from_html():
    html = """<html><head><title>Doc</title></head><body>
      <nav>menu junk</nav>
      <article><p>%s</p></article>
      <footer>all rights reserved</footer></body></html>""" % ("Real content here. " * 40)
    text, title, _ = extract_content(html, "https://x.com")
    assert "Real content here" in text
    assert "menu junk" not in text


def test_collapse_removes_boilerplate():
    out = _collapse("Accept all cookies\nGenuine paragraph with substance here.\n\n\nx")
    assert "Genuine paragraph" in out
    assert "Accept all cookies" not in out


def test_chunk_document():
    d = Document(url="https://a.com", content="\n".join(
        [f"Paragraph {i} with a reasonable amount of text to exceed the minimum length." * 3
         for i in range(12)]))
    chunks = chunk_document(d, target_chars=500, max_chunks=4)
    assert 0 < len(chunks) <= 4
    assert all(c.doc is d for c in chunks)


# ---------------------------------------------------------------- brain
def test_parse_json_handles_fences():
    assert parse_json('```json\n["a","b"]\n```') == ["a", "b"]
    assert parse_json('Sure! {"0":0.9}') == {"0": 0.9}
    assert parse_json("not json at all") is None


def test_document_to_source_shape():
    d = Document(url="https://a.com/x", title="T", domain="a.com")
    d.cite_id = 3
    d.score = 1.234567
    out = d.to_source()
    assert out["id"] == 3
    assert out["score"] == 1.2346
    assert "signals" in out


if __name__ == "__main__":
    sys.exit(pytest.main([__file__, "-v", "--tb=short"]))
