from __future__ import annotations

from beaver.interfaces.channels.connections import MessageDedupeStore


def test_message_dedupe_store_completes_and_dedupes_completed(tmp_path) -> None:
    store = MessageDedupeStore(tmp_path / "message_dedupe.json")

    first = store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=1)
    store.complete(first.dedupe_key, message_id="msg_1")
    duplicate = store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=2)

    assert first.should_process is True
    assert duplicate.should_process is False
    assert duplicate.status == "completed"
    assert duplicate.http_status == 200


def test_message_dedupe_store_returns_conflict_for_active_processing(tmp_path) -> None:
    store = MessageDedupeStore(tmp_path / "message_dedupe.json", processing_ttl_seconds=60)

    store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=1)
    duplicate = store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=2)

    assert duplicate.should_process is False
    assert duplicate.status == "processing"
    assert duplicate.http_status == 409
    assert duplicate.retry_after_seconds == 5


def test_message_dedupe_store_reprocesses_stale_processing(tmp_path) -> None:
    store = MessageDedupeStore(tmp_path / "message_dedupe.json", processing_ttl_seconds=0)

    store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=1)
    stale = store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=2)

    assert stale.should_process is True
    assert stale.status == "processing"
    assert stale.record.delivery_attempts == 2


def test_message_dedupe_store_reprocesses_failed_records(tmp_path) -> None:
    store = MessageDedupeStore(tmp_path / "message_dedupe.json")

    first = store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=1)
    store.fail(first.dedupe_key, error="runtime rejected")
    retry = store.begin(connection_id="conn_1", event_id="evt_1", delivery_attempt=2)

    assert retry.should_process is True
    assert retry.record.delivery_attempts == 2
    assert retry.record.last_error is None
