from __future__ import annotations

from collections.abc import Iterator

import pytest

from osm_lead_source_service.errors import PbfValidationError
from osm_lead_source_service.pbf import PbfParseLimits
from osm_lead_source_service.pbf import parser as parser_module


def test_duplicate_payload_is_rejected_without_scanning_remaining_fields(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    def fields(data: bytes) -> Iterator[tuple[int, int, int | bytes]]:
        del data
        yield 1, 2, b"first"
        yield 3, 2, b"second"
        raise AssertionError("validator consumed fields after duplicate payload")

    monkeypatch.setattr(parser_module, "_protobuf_fields", fields)

    with pytest.raises(PbfValidationError, match="exactly one approved payload"):
        parser_module._validate_blob(b"ignored", PbfParseLimits())


def test_duplicate_raw_size_is_rejected_without_scanning_remaining_fields(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    def fields(data: bytes) -> Iterator[tuple[int, int, int | bytes]]:
        del data
        yield 2, 0, 5
        yield 2, 0, 5
        raise AssertionError("validator consumed fields after duplicate raw_size")

    monkeypatch.setattr(parser_module, "_protobuf_fields", fields)

    with pytest.raises(PbfValidationError, match="raw_size field is duplicated"):
        parser_module._validate_blob(b"ignored", PbfParseLimits())


def test_duplicate_blob_header_fields_are_rejected() -> None:
    duplicated_type = b"\x0a\x07OSMData\x0a\x07OSMData\x18\x01"
    duplicated_size = b"\x0a\x07OSMData\x18\x01\x18\x01"

    with pytest.raises(PbfValidationError, match="type field is duplicated"):
        parser_module._parse_blob_header(duplicated_type)
    with pytest.raises(PbfValidationError, match="datasize field is duplicated"):
        parser_module._parse_blob_header(duplicated_size)
