from types import SimpleNamespace

import pytest

from app.api.routers import scholars as scholars_router


class _FakeSession:
    def __init__(self) -> None:
        self.commits = 0
        self.rollbacks = 0

    async def commit(self) -> None:
        self.commits += 1

    async def rollback(self) -> None:
        self.rollbacks += 1


@pytest.mark.asyncio
async def test_create_hydration_skips_when_global_throttle_active(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    profile = SimpleNamespace(
        id=42,
        profile_image_url=None,
        display_name="",
    )

    async def _fail_hydration(*_args, **_kwargs):
        raise AssertionError("hydrate_profile_metadata should not run when throttle is active")

    monkeypatch.setattr(
        scholars_router.scholar_rate_limit,
        "remaining_scholar_slot_seconds",
        lambda **_kwargs: 3.5,
    )
    monkeypatch.setattr(
        scholars_router.scholar_service,
        "hydrate_profile_metadata",
        _fail_hydration,
    )

    result = await scholars_router._hydrate_scholar_metadata_if_needed(
        db_session=None,
        profile=profile,
        source=object(),
        user_id=7,
    )

    assert result is profile


@pytest.mark.asyncio
async def test_create_hydration_runs_when_throttle_is_clear(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    profile = SimpleNamespace(
        id=84,
        profile_image_url=None,
        display_name="",
    )

    async def _hydrate_profile_metadata(*_args, **_kwargs):
        profile.display_name = "Ada Lovelace"
        return profile

    monkeypatch.setattr(
        scholars_router.scholar_rate_limit,
        "remaining_scholar_slot_seconds",
        lambda **_kwargs: 0.0,
    )
    monkeypatch.setattr(
        scholars_router.scholar_service,
        "hydrate_profile_metadata",
        _hydrate_profile_metadata,
    )

    result = await scholars_router._hydrate_scholar_metadata_if_needed(
        db_session=None,
        profile=profile,
        source=object(),
        user_id=8,
    )

    assert result.display_name == "Ada Lovelace"


@pytest.mark.asyncio
async def test_initial_scrape_job_enqueued_on_create(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    profile = SimpleNamespace(id=101)
    session = _FakeSession()
    upsert_calls: list[dict[str, object]] = []

    async def _fake_upsert_job(*_args, **kwargs):
        upsert_calls.append(kwargs)

    monkeypatch.setattr(
        scholars_router,
        "_auto_enqueue_new_scholar_enabled",
        lambda: True,
    )
    monkeypatch.setattr(
        scholars_router.ingestion_queue_service,
        "upsert_job",
        _fake_upsert_job,
    )

    queued = await scholars_router._enqueue_initial_scrape_job_for_scholar(
        session,
        profile=profile,
        user_id=9,
    )

    assert queued is True
    assert session.commits == 1
    assert session.rollbacks == 0
    assert upsert_calls[0]["reason"] == scholars_router.INITIAL_SCHOLAR_SCRAPE_QUEUE_REASON


@pytest.mark.asyncio
async def test_initial_scrape_job_not_enqueued_when_disabled(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    profile = SimpleNamespace(id=202)
    session = _FakeSession()

    monkeypatch.setattr(
        scholars_router,
        "_auto_enqueue_new_scholar_enabled",
        lambda: False,
    )

    queued = await scholars_router._enqueue_initial_scrape_job_for_scholar(
        session,
        profile=profile,
        user_id=11,
    )

    assert queued is False
    assert session.commits == 0
    assert session.rollbacks == 0
