"""Tests for web discovered URL repository behavior."""

from __future__ import annotations

from types import SimpleNamespace
from unittest.mock import AsyncMock

import pytest

from repo_core.domains.web.url.model import WebDiscoveredUrl
from repo_core.domains.web.url.repository import WebDiscoveredUrlRepository


@pytest.mark.asyncio
async def test_find_due_for_crawl_orders_by_fair_priority(monkeypatch):
    repo = WebDiscoveredUrlRepository(model=WebDiscoveredUrl)
    find = AsyncMock(return_value=[])
    monkeypatch.setattr(repo, "find", find)

    await repo.find_due_for_crawl("seed-1", limit=None)

    assert find.await_count == 1
    _, kwargs = find.call_args
    assert kwargs["order_by"] == ["fair_priority", "next_crawl"]
    assert "limit" not in kwargs


@pytest.mark.asyncio
async def test_find_due_for_crawl_includes_failed_status(monkeypatch):
    repo = WebDiscoveredUrlRepository(model=WebDiscoveredUrl)
    find = AsyncMock(return_value=[])
    monkeypatch.setattr(repo, "find", find)

    await repo.find_due_for_crawl("seed-1")

    criteria = find.call_args.args[1]
    assert "FAILED" in criteria["status"][1]


@pytest.mark.asyncio
async def test_mark_queued_resets_attempt_state(monkeypatch):
    repo = WebDiscoveredUrlRepository(model=WebDiscoveredUrl)
    find_by_id = AsyncMock(return_value=SimpleNamespace(priority=11))
    update_by_id = AsyncMock(return_value=None)
    monkeypatch.setattr(repo, "find_by_id", find_by_id)
    monkeypatch.setattr(repo, "update_by_id", update_by_id)

    await repo.mark_queued("url-1")

    update_by_id.assert_awaited_once()
    payload = update_by_id.call_args.args[2]
    assert payload["status"].value == "QUEUED"
    assert payload["attempt_number"] == 0
    assert payload["fair_priority"] == 11


@pytest.mark.asyncio
async def test_mark_attempted_updates_attempt_state(monkeypatch):
    repo = WebDiscoveredUrlRepository(model=WebDiscoveredUrl)
    update_by_id = AsyncMock(return_value=None)
    monkeypatch.setattr(repo, "update_by_id", update_by_id)

    await repo.mark_attempted("url-1", 2, 7)

    update_by_id.assert_awaited_once()
    payload = update_by_id.call_args.args[2]
    assert payload["attempt_number"] == 2
    assert payload["fair_priority"] == 7


@pytest.mark.asyncio
async def test_mark_failed_schedules_retry(monkeypatch):
    repo = WebDiscoveredUrlRepository(model=WebDiscoveredUrl)
    update_by_id = AsyncMock(return_value=None)
    monkeypatch.setattr(repo, "update_by_id", update_by_id)

    await repo.mark_failed("url-1", "2026-07-26T11:00:00+00:00")

    update_by_id.assert_awaited_once()
    payload = update_by_id.call_args.args[2]
    assert payload["status"].value == "FAILED"
    assert payload["next_crawl"] == "2026-07-26T11:00:00+00:00"