"""Predatory data source refuses to overwrite a healthy snapshot when
the upstream fetch returns suspiciously few rows.

This guards against the partial-CDN-outage failure mode: if 2 of the 3
upstream CSVs return 0 rows, the resulting predatory.json would silently
disable predatory filtering for everyone. The floor check raises
instead, leaving the previous good snapshot in place.
"""

from __future__ import annotations

from unittest.mock import MagicMock, patch

import pytest

from local_deep_research.journal_quality.data_sources import (
    predatory as pred_mod,
)
from local_deep_research.journal_quality.data_sources.predatory import (
    PredatorySource,
)


def _csv_response(text: str) -> MagicMock:
    resp = MagicMock()
    resp.raise_for_status = MagicMock()
    resp.text = text
    return resp


def test_below_floor_raises_and_does_not_overwrite(tmp_path, monkeypatch):
    """3 CSVs all near-empty → fetch raises before writing the file.

    A pre-existing predatory.json (simulating last good build) must
    survive on-disk so the filter keeps working with stale-but-valid
    data instead of silently no-op-ing.
    """
    monkeypatch.setattr(pred_mod, "_MIN_PREDATORY_TOTAL", 100)

    existing = tmp_path / "predatory.json"
    existing.write_bytes(b'{"sentinel": "previous good build"}')

    # Only 1 publisher + 1 journal + 0 hijacked = 2 entries (well below 100)
    publishers_csv = "name,url\nBad Publisher,http://example.com\n"
    journals_csv = "name,url\nBad Journal,http://example.com\n"
    hijacked_csv = "hijacked,hijackedurl,authentic,authenticurl\n"

    with patch(
        "local_deep_research.security.safe_requests.safe_get_with_retries",
    ) as mock_get:
        mock_get.side_effect = [
            _csv_response(publishers_csv),
            _csv_response(journals_csv),
            _csv_response(hijacked_csv),
        ]
        with pytest.raises(RuntimeError, match="suspiciously few records"):
            PredatorySource().fetch(tmp_path)

    # Existing snapshot is intact (no partial overwrite).
    assert existing.read_bytes() == b'{"sentinel": "previous good build"}'


def test_above_floor_writes_normally(tmp_path, monkeypatch):
    """A healthy fetch (well above the floor) writes the snapshot."""
    monkeypatch.setattr(pred_mod, "_MIN_PREDATORY_TOTAL", 5)

    publishers_csv = "name,url\n" + "\n".join(
        f"Pub {i},http://p{i}.example" for i in range(10)
    )
    journals_csv = "name,url\n"
    hijacked_csv = "hijacked,hijackedurl,authentic,authenticurl\n"

    with patch(
        "local_deep_research.security.safe_requests.safe_get_with_retries",
    ) as mock_get:
        mock_get.side_effect = [
            _csv_response(publishers_csv),
            _csv_response(journals_csv),
            _csv_response(hijacked_csv),
        ]
        result = PredatorySource().fetch(tmp_path)

    assert result == 10
    assert (tmp_path / "predatory.json").exists()
