from goodnews.taxonomy import coerce_tags
from goodnews.db import connect, init_db
from goodnews.llm import normalize_scores, upsert_article_score
from goodnews import queries


def test_coerce_tags_validates_dedupes_caps():
    assert coerce_tags(["science", "space", "bogus", "science"]) == ["science", "space"]
    assert coerce_tags(["science", "space", "animals", "nature", "archaeology"]) == \
        ["science", "space", "animals", "nature"]  # capped at 4
    assert coerce_tags("not-a-list") == []
    assert coerce_tags(None) == []


def test_normalize_includes_valid_tags_only():
    s = normalize_scores({"topic": "technology", "flavor": "discovery", "tags": ["space", "nope"]}, "m")
    assert s["topic"] == "technology"   # new primary topic accepted
    assert s["tags"] == ["space"]


def _db():
    c = connect(":memory:"); init_db(c)
    c.execute("INSERT INTO sources (id,name,feed_url,trust_score) VALUES (1,'S','http://s/f',5)")
    for aid in (1, 2):
        c.execute("INSERT INTO articles (id,source_id,canonical_url,title,url_hash) VALUES (?,1,?,?,?)",
                  (aid, f"http://s/{aid}", f"t{aid}", f"h{aid}"))
    c.commit()
    return c


def _score(tags, topic="science"):
    return normalize_scores({"topic": topic, "flavor": "discovery", "accepted": True,
                             "constructive_score": 7, "agency_score": 2, "human_benefit_score": 2,
                             "tags": tags}, "m")


def test_upsert_writes_tags_and_feed_filters_by_tag():
    c = _db()
    upsert_article_score(c, 1, _score(["space", "animals"]))
    upsert_article_score(c, 2, _score(["community"], topic="community"))
    c.commit()
    assert [r["id"] for r in queries.feed(c, tag="space", limit=50)] == [1]
    assert [r["id"] for r in queries.feed(c, tag="community", limit=50)] == [2]
    row1 = next(r for r in queries.feed(c, limit=50) if r["id"] == 1)
    assert set(row1["tags"].split(",")) == {"space", "animals"}


def test_reclassify_replaces_old_tags():
    c = _db()
    upsert_article_score(c, 1, _score(["space", "animals"]))
    c.commit()
    upsert_article_score(c, 1, _score(["science"]))  # re-tag
    c.commit()
    assert [r["id"] for r in queries.feed(c, tag="animals", limit=50)] == []   # old tag gone
    assert [r["id"] for r in queries.feed(c, tag="science", limit=50)] == [1]


def test_tag_counts():
    c = _db()
    upsert_article_score(c, 1, _score(["space", "science"]))
    upsert_article_score(c, 2, _score(["science"]))
    c.commit()
    counts = queries.tag_counts(c)
    assert counts["science"] == 2 and counts["space"] == 1
