from __future__ import annotations

import base64
from pathlib import Path
from types import SimpleNamespace

import pytest

from osm_lead_source_service.errors import PbfDownloadRejected
from osm_lead_source_service.pbf import ApprovedTestPbfDownload
from osm_lead_source_service.pbf.download import _validate_cached_file

_FIXTURE = Path(__file__).parents[2] / "fixtures" / "pbf" / "tiny.osm.pbf.b64"
_SHA256 = "1f181fa63b838de88c5c7d8ecff2a014ca52a9349c6470fd2656ad3c9e0ddb8c"


def test_cached_file_change_during_hashing_is_rejected(
    tmp_path: Path,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    path = tmp_path / f"{_SHA256}.osm.pbf"
    path.write_bytes(base64.b64decode(_FIXTURE.read_text(encoding="ascii")))
    real = path.lstat()
    calls = 0

    def changing_lstat(self: Path) -> SimpleNamespace:
        nonlocal calls
        assert self == path
        calls += 1
        return SimpleNamespace(
            st_mode=real.st_mode,
            st_dev=real.st_dev,
            st_ino=real.st_ino,
            st_size=real.st_size,
            st_mtime=real.st_mtime,
            st_mtime_ns=real.st_mtime_ns,
            st_ctime_ns=real.st_ctime_ns + (1 if calls > 1 else 0),
        )

    monkeypatch.setattr(Path, "lstat", changing_lstat)
    settings = ApprovedTestPbfDownload(
        region_id="fixture",
        url="http://127.0.0.1:8765/tiny.osm.pbf",
        expected_sha256=_SHA256,
        expected_size_bytes=438,
    )
    with pytest.raises(PbfDownloadRejected, match="changed during validation"):
        _validate_cached_file(path, settings)
