from types import SimpleNamespace

import pytest
from fastapi.testclient import TestClient

from goodnews import summarize
from goodnews.db import connect, init_db


def _db(path):
    c = connect(str(path)); init_db(c)
    c.execute("INSERT INTO sources (id,name,feed_url,trust_score) VALUES (1,'NPR','http://s/f',5)")
    c.execute("INSERT INTO articles (id,source_id,canonical_url,title,url_hash,description) "
              "VALUES (1,1,'https://npr.org/x','Voles return','h1','A snippet.')")
    c.execute("INSERT INTO article_scores (article_id,accepted,reason_text) VALUES (1,1,'Hopeful.')")
    c.commit()
    return c


def test_generate_caches_summary(tmp_path, monkeypatch):
    c = _db(tmp_path / "t.sqlite3")
    monkeypatch.setattr(summarize, "_fetch_text", lambda url: "Full article body about voles.")
    monkeypatch.setattr(summarize, "summarize_article", lambda client, t, s, b: "Our own short summary.")
    monkeypatch.setattr(summarize, "explain_article",
                        lambda client, t, s, b: {"what_happened": "w", "why_matters": "m", "why_belongs": "b"})
    # avoid constructing a real LLM client
    monkeypatch.setattr(summarize.LocalModelClient, "from_env", classmethod(lambda cls: SimpleNamespace(model="m")))
    out = summarize.generate_summary(c, 1)
    assert out == "Our own short summary."
    assert summarize.get_summary(c, 1) == "Our own short summary."
    # second call is a cache hit (no regeneration)
    monkeypatch.setattr(summarize, "summarize_article", lambda *a: "DIFFERENT")
    assert summarize.generate_summary(c, 1) == "Our own short summary."


def test_summary_endpoint_pending_then_ready(tmp_path, monkeypatch):
    db = tmp_path / "t.sqlite3"
    _db(db).close()
    monkeypatch.setenv("GOODNEWS_DB", str(db))
    monkeypatch.setenv("GOODNEWS_PUBLIC_BASE_URL", "https://upbeatbytes.com")
    import importlib
    import goodnews.api as api
    importlib.reload(api)
    # stub the actual generation the background task runs
    monkeypatch.setattr(
        api.summarize, "generate_summary",
        lambda conn, aid, client=None: conn.execute(
            "INSERT OR REPLACE INTO article_summaries (article_id, summary) VALUES (?, 'Cached summary.')", (aid,)
        ) and conn.commit(),
    )
    tc = TestClient(api.create_app())
    first = tc.get("/api/summary/1").json()
    assert first["status"] == "pending"
    # TestClient runs the background task; the next call sees the cache
    assert tc.get("/api/summary/1").json() == {"status": "ready", "summary": "Cached summary.", "explanation": None}
    # and the share page now embeds it (no pending poll)
    html = tc.get("/a/1").text
    assert "Cached summary." in html
