import httpx
import pytest

from src import main
from src.completed_filed_review_store import CompletedFiledReviewStore


def receipt(repository="stackchain/api", number=9, updated_at="2026-08-15T12:00:00Z"):
    return {"repository": repository, "number": number, "updated_at": updated_at}


def test_receipts_merge_without_lost_updates_and_remain_account_scoped(tmp_path):
    store = CompletedFiledReviewStore(tmp_path / "completed-filed.sqlite3")

    first = store.merge(" Timmy ", [receipt()])
    second = store.merge("timmy", [receipt("stackchain/web", 4)])

    assert first == {"receipts": [receipt()]}
    assert second == {"receipts": [receipt(), receipt("stackchain/web", 4)]}
    assert store.get("TIMMY") == second
    assert store.get("alexander") == {"receipts": []}


def test_receipts_keep_newest_revision_and_bound_each_account(tmp_path):
    store = CompletedFiledReviewStore(tmp_path / "completed-filed.sqlite3", limit=2)
    newer = receipt(updated_at="2026-08-16T12:00:00Z")

    store.merge("timmy", [newer])
    assert store.merge("timmy", [receipt()]) == {"receipts": [newer]}
    bounded = store.merge("timmy", [receipt("stackchain/web", 2), receipt("stackchain/docs", 3)])

    assert bounded == {"receipts": [receipt("stackchain/web", 2), receipt("stackchain/docs", 3)]}


@pytest.mark.parametrize("candidate", [
    {"repository": "bad", "number": 1, "updated_at": "2026-08-15T12:00:00Z"},
    {"repository": "stackchain/api", "number": 0, "updated_at": "2026-08-15T12:00:00Z"},
    {"repository": "stackchain/api", "number": 1, "updated_at": "yesterday"},
])
def test_receipts_reject_invalid_records(tmp_path, candidate):
    store = CompletedFiledReviewStore(tmp_path / "completed-filed.sqlite3")
    with pytest.raises(ValueError):
        store.merge("timmy", [candidate])


@pytest.mark.anyio
async def test_completed_filed_review_api_is_authenticated_csrf_protected_and_no_store(monkeypatch, tmp_path):
    monkeypatch.setenv("STACKCHAIN_DASHBOARD_AUTH_MODE", "operator")
    monkeypatch.setenv("STACKCHAIN_DASHBOARD_ACCESS_TOKEN", "correct horse battery staple")
    monkeypatch.setenv("STACKCHAIN_DASHBOARD_SESSION_SECRET", "a-separate-session-signing-secret-with-enough-entropy")
    monkeypatch.setenv("STACKCHAIN_SESSION_DB", str(tmp_path / "sessions.sqlite3"))
    monkeypatch.setenv("STACKCHAIN_LOGIN_ATTEMPT_DB", str(tmp_path / "login.sqlite3"))
    monkeypatch.setenv("STACKCHAIN_COMPLETED_FILED_REVIEW_DB", str(tmp_path / "completed.sqlite3"))

    async def user():
        return {"id": 1, "login": "Timmy"}

    monkeypatch.setattr(main, "current_user", user)
    transport = httpx.ASGITransport(app=main.app)
    async with httpx.AsyncClient(transport=transport, base_url="https://test") as client:
        await client.post("/api/v1/session", json={"access_token": "correct horse battery staple"})
        forbidden = await client.post("/api/v1/completed-filed-reviews", json={"receipts": [receipt()]})
        headers = {"Origin": "https://test", "X-CSRF-Token": client.cookies["stackchain_csrf"]}
        saved = await client.post(
            "/api/v1/completed-filed-reviews", json={"receipts": [receipt()]}, headers=headers
        )
        fetched = await client.get("/api/v1/completed-filed-reviews")

    assert forbidden.status_code == 403
    assert saved.status_code == 200
    assert saved.json() == {"receipts": [receipt()]}
    assert fetched.json() == saved.json()
    assert fetched.headers["cache-control"] == "no-store"
