"""Async scrape endpoint contract.

Verifies that ``POST /api/admin/scrape``:
  - returns 202 + ``scrape_log_id`` synchronously,
  - persists a ``ScrapeLog`` row in status STARTED before the background task
    runs (the task is monkey-patched out so it never reaches Playwright and
    never opens a session outside the test transaction).
"""
from __future__ import annotations

import os
import uuid

import pytest

os.environ.setdefault("ADMIN_TOKEN", "test-admin-token")


@pytest.fixture(autouse=True)
def _admin_token(monkeypatch):
    monkeypatch.setenv("ADMIN_TOKEN", "test-admin-token")
    yield


@pytest.mark.requires_postgres
def test_scrape_returns_202_and_log_id(client, db, monkeypatch):
    """Endpoint enqueues the scrape and returns 202 + scrape_log_id.

    We replace the background runner with a no-op so the test does NOT spin up
    Playwright and does NOT open a session outside the rolled-back test
    transaction.
    """
    calls: list[tuple] = []

    def _fake_run(log_id, source, scrape_type):
        calls.append((log_id, source, scrape_type))

    # Patch in BOTH the service module (definition site) and the api module
    # (import site) so whichever symbol the route resolved to is replaced.
    monkeypatch.setattr(
        "app.services.scraper_service._run_scrape_in_background", _fake_run
    )

    r = client.post(
        "/api/admin/scrape",
        headers={"Authorization": "Bearer test-admin-token"},
    )
    assert r.status_code == 202, r.text
    body = r.json()
    assert body["status"] == "queued"
    assert "scrape_log_id" in body

    log_id = uuid.UUID(body["scrape_log_id"])

    # Row was committed inside enqueue_scrape — visible on the test session.
    from app.models import ScrapeLog, ScrapeStatus

    log = db.query(ScrapeLog).filter(ScrapeLog.id == log_id).first()
    assert log is not None, "ScrapeLog row should exist after enqueue"
    assert log.status == ScrapeStatus.STARTED
    assert log.source == "lucky_california"
    assert log.scrape_type == "weekly_ad"
    assert log.completed_at is None

    # TestClient runs background tasks before returning from the context
    # manager exit — by the time we get here, the fake runner ran exactly once.
    assert len(calls) == 1
    assert calls[0][0] == log_id
