import pytest

from goodnews.db import connect, init_db
from goodnews.sources import (
    list_candidates,
    promote_candidate,
    reject_candidate,
    restore_candidate,
    save_candidate,
)


@pytest.fixture
def conn():
    c = connect(":memory:")
    init_db(c)
    yield c
    c.close()


def test_save_and_list_candidate(conn):
    cand = save_candidate(conn, "http://x/feed", preview={"acceptance_rate": 0.8, "sampled": 10}, name="X")
    assert cand["status"] == "quarantined"
    rows = list_candidates(conn)
    assert len(rows) == 1 and rows[0]["feed_url"] == "http://x/feed"


def test_re_preview_preserves_curator_status(conn):
    save_candidate(conn, "http://x/feed")
    reject_candidate(conn, list_candidates(conn)[0]["id"])
    # Re-previewing must NOT revive a rejected feed.
    save_candidate(conn, "http://x/feed", preview={"acceptance_rate": 0.9})
    assert list_candidates(conn)[0]["status"] == "rejected"


def test_restore_sends_rejected_back_to_staging(conn):
    save_candidate(conn, "http://x/feed")
    cid = list_candidates(conn)[0]["id"]
    reject_candidate(conn, cid)
    assert list_candidates(conn)[0]["status"] == "rejected"
    # restore → back to staging ('suggested'), re-enters the pending queue
    assert restore_candidate(conn, cid) is True
    assert list_candidates(conn)[0]["status"] == "suggested"
    # restoring a non-rejected candidate is a no-op (only un-rejects)
    assert restore_candidate(conn, cid) is False


def test_promote_creates_inactive_source_and_marks_promoted(conn):
    cand = save_candidate(conn, "http://x/feed", name="Lovely Feed")
    source_id = promote_candidate(conn, cand["id"])  # inactive by default

    src = conn.execute("SELECT name, active, status FROM sources WHERE id = ?", (source_id,)).fetchone()
    assert src["name"] == "Lovely Feed"
    assert src["active"] == 0  # active-on-approval: not polled until activated
    assert src["status"] == "paused"  # status mirrors active — no drift (active=0 ⇒ paused)

    status = conn.execute("SELECT status FROM source_candidates WHERE id = ?", (cand["id"],)).fetchone()["status"]
    assert status == "promoted"


def test_promote_active_flag(conn):
    cand = save_candidate(conn, "http://y/feed", name="Y")
    sid = promote_candidate(conn, cand["id"], active=True)
    src = conn.execute("SELECT active, status FROM sources WHERE id = ?", (sid,)).fetchone()
    assert src["active"] == 1 and src["status"] == "active"  # both set together


def test_promote_unknown_raises(conn):
    with pytest.raises(ValueError):
        promote_candidate(conn, 999)


def test_name_derived_from_url_when_missing(conn):
    cand = save_candidate(conn, "https://news.example.org/rss")
    sid = promote_candidate(conn, cand["id"])
    assert conn.execute("SELECT name FROM sources WHERE id = ?", (sid,)).fetchone()["name"] == "news.example.org"
