"""Tests for scripts/sync_motion_content.py.

Tests retry logic in _fetch_body_text and permanent-failure audit recording.
"""

import requests
from unittest.mock import MagicMock, patch

import scripts.sync_motion_content as s


def test_parse_besluit_simple():
    xml = '<Besluit id="b1' + '">\n<Zaak ref="z1"/>\n</Besluit>'
    parsed = s.parse_besluit(xml)
    assert parsed["id"] == "b1"


def test_fetch_body_text_retries_on_transient_error(monkeypatch):
    """_fetch_body_text retries after a ConnectionError and returns text on success."""
    session = MagicMock()
    call_count = {"n": 0}

    def fake_get(url, timeout=30):
        call_count["n"] += 1
        if call_count["n"] == 1:
            raise requests.exceptions.ConnectionError("timeout")
        # Second attempt succeeds
        resp = MagicMock()
        resp.status_code = 200
        resp.text = "<p>body text here</p>"
        resp.raise_for_status.return_value = None
        return resp

    session.get.side_effect = fake_get

    # Patch time.sleep to avoid delays in tests
    monkeypatch.setattr("time.sleep", lambda s: None)

    result = s._fetch_body_text("ext123", session, retries=3)

    assert result is not None
    assert "body text here" in result
    assert call_count["n"] == 2  # failed once, succeeded on second


def test_fetch_body_text_permanent_failure_records_audit(monkeypatch):
    """When all retries are exhausted, audit_event is recorded via database.db."""
    session = MagicMock()
    session.get.side_effect = requests.exceptions.ConnectionError("always fails")

    monkeypatch.setattr("time.sleep", lambda s: None)

    # Capture the audit event call
    audit_calls = []

    import database

    monkeypatch.setattr(
        database.db,
        "append_audit_event",
        lambda actor_id, action, **kwargs: (
            audit_calls.append({"action": action, **kwargs}) or True
        ),
    )

    result = s._fetch_body_text("ext_fail", session, retries=3)

    assert result is None
    assert len(audit_calls) >= 1
    assert audit_calls[0]["action"] == "body_fetch_failed"
    assert audit_calls[0]["target_id"] == "ext_fail"


def test_fetch_body_text_retries_on_5xx(monkeypatch):
    """5xx responses are treated as transient; retried before giving up."""
    session = MagicMock()
    call_count = {"n": 0}

    def fake_get(url, timeout=30):
        call_count["n"] += 1
        resp = MagicMock()
        if call_count["n"] < 3:
            resp.status_code = 503
            resp.raise_for_status.return_value = None
        else:
            resp.status_code = 200
            resp.text = "clean text"
            resp.raise_for_status.return_value = None
        return resp

    session.get.side_effect = fake_get
    monkeypatch.setattr("time.sleep", lambda s: None)

    result = s._fetch_body_text("ext_5xx", session, retries=3)

    assert result is not None
    assert call_count["n"] == 3
