from __future__ import annotations

from datetime import datetime, timezone
from pathlib import Path
from types import SimpleNamespace

import pytest

from osm_lead_source_service.markets import GeoBounds, get_english_market
from osm_lead_source_service.pbf.catalog import CatalogFeature, MarketSourceShard
from osm_lead_source_service.pbf.extract import ExtractedPbf
from osm_lead_source_service.pbf.geofabrik import AcquiredPbf
from osm_lead_source_service.pbf.market import run_market_shard


def _feature(feature_id: str) -> CatalogFeature:
    return CatalogFeature(
        feature_id,
        None,
        feature_id,
        f"https://download.geofabrik.de/test/{feature_id}-latest.osm.pbf",
    )


def _acquisition(tmp_path: Path) -> AcquiredPbf:
    source = tmp_path / "source.osm.pbf"
    source.write_bytes(b"source")
    now = datetime(2026, 7, 20, tzinfo=timezone.utc)
    return AcquiredPbf(
        "source-test",
        "https://download.geofabrik.de/test/source-latest.osm.pbf",
        source,
        "a" * 64,
        "b" * 32,
        source.stat().st_size,
        now,
        now,
        False,
    )


def _report() -> SimpleNamespace:
    return SimpleNamespace(
        profile=SimpleNamespace(profile_id="luxeillum", version="0.1.0-draft"),
        report_hash="c" * 64,
        leads=(object(), object()),
        review_items=(),
    )


def test_runs_dedicated_country_shard_without_extraction(
    tmp_path: Path,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    from osm_lead_source_service.pbf import market

    captured: dict[str, object] = {}
    acquisition = _acquisition(tmp_path)
    monkeypatch.setattr(market, "acquire_region", lambda *_args, **_kwargs: acquisition)

    def fake_shadow(**kwargs: object) -> SimpleNamespace:
        captured.update(kwargs)
        return _report()

    monkeypatch.setattr(market, "run_profile_shadow", fake_shadow)
    shard = MarketSourceShard(get_english_market("IE"), _feature("ireland"))

    result = run_market_shard(shard, tmp_path / "cache")

    approved = captured["approved_input"]
    context = captured["normalization_context"]
    assert result.extraction is None
    assert approved.local_path == acquisition.local_path
    assert captured["region_id"] == "ie"
    assert context.country_code == "IE"
    assert result.evidence_mapping()["writes_enabled"] is False


def test_shared_country_uses_bounded_extraction(
    tmp_path: Path,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    from osm_lead_source_service.pbf import market

    acquisition = _acquisition(tmp_path)
    extracted_path = tmp_path / "singapore.osm.pbf"
    extracted_path.write_bytes(b"singapore")
    bounds = GeoBounds(1_036_000_000, 12_000_000, 1_041_000_000, 16_000_000)
    extraction = ExtractedPbf(
        extracted_path,
        "d" * 64,
        extracted_path.stat().st_size,
        acquisition.content_sha256,
        bounds,
        False,
    )
    captured: dict[str, object] = {}
    monkeypatch.setattr(market, "acquire_region", lambda *_args, **_kwargs: acquisition)
    monkeypatch.setattr(market, "extract_country_pbf", lambda *_args, **_kwargs: extraction)

    def fake_shadow(**kwargs: object) -> SimpleNamespace:
        captured.update(kwargs)
        return _report()

    monkeypatch.setattr(market, "run_profile_shadow", fake_shadow)
    shard = MarketSourceShard(get_english_market("SG"), _feature("shared"), bounds)

    result = run_market_shard(shard, tmp_path / "cache")

    approved = captured["approved_input"]
    assert result.extraction is extraction
    assert approved.local_path == extracted_path
    assert approved.content_sha256 == "d" * 64


def test_rejects_unbounded_source_limit(tmp_path: Path) -> None:
    shard = MarketSourceShard(get_english_market("IE"), _feature("ireland"))
    with pytest.raises(ValueError, match="outside"):
        run_market_shard(shard, tmp_path, max_source_bytes=1)
