"""Generic read-only market-shard acquisition, extraction, and profiling."""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from ..domain.models import ProfileVersion
from ..markets import EnglishMarket
from ..normalization.models import NormalizationContext
from ..profiles import ProfileEvaluator, builtin_profile_registry
from ..shadow import ShadowSourceReport, run_profile_shadow
from .catalog import MarketSourceShard
from .extract import ExtractedPbf, extract_country_pbf
from .geofabrik import AcquiredPbf, GeofabrikRegion, acquire_region
from .models import PbfParseLimits, VerifiedPbfInput
from .parser import OsmiumPbfParser

_MARKET_PROFILE = ProfileVersion("luxeillum", "0.1.0-draft")
_MAX_SOURCE_BYTES = 4 * 1024 * 1024 * 1024


@dataclass(frozen=True, slots=True)
class MarketShardResult:
    """Immutable evidence for one completed country/shard shadow run."""

    market: EnglishMarket
    shard: MarketSourceShard
    acquisition: AcquiredPbf
    extraction: ExtractedPbf | None
    report: ShadowSourceReport

    def evidence_mapping(self) -> dict[str, object]:
        return {
            "acquisition": self.acquisition.as_mapping(),
            "country": {
                "calling_code": self.market.calling_code,
                "country_code": self.market.country_code,
                "display_name": self.market.display_name,
            },
            "extraction": (None if self.extraction is None else self.extraction.as_mapping()),
            "lead_count": len(self.report.leads),
            "mode": "shadow-read-only",
            "noco_access": False,
            "profile": {
                "id": self.report.profile.profile_id,
                "version": self.report.profile.version,
            },
            "report_hash": self.report.report_hash,
            "review_count": len(self.report.review_items),
            "shard": {
                "feature_id": self.shard.feature.feature_id,
                "shard_id": self.shard.shard_id,
                "source_url": self.shard.feature.pbf_url,
            },
            "writes_enabled": False,
        }


def _source_region(shard: MarketSourceShard, max_source_bytes: int) -> GeofabrikRegion:
    return GeofabrikRegion(
        region_id=f"source-{shard.feature.feature_id}",
        display_name=shard.feature.display_name,
        country_code=shard.market.country_code,
        calling_code=shard.market.calling_code,
        pbf_url=shard.feature.pbf_url,
        checksum_url=f"{shard.feature.pbf_url}.md5",
        max_size_bytes=max_source_bytes,
    )


def run_market_shard(
    shard: MarketSourceShard,
    cache_dir: Path,
    *,
    timeout_seconds: float = 120.0,
    extraction_timeout_seconds: float = 7200.0,
    max_source_bytes: int = _MAX_SOURCE_BYTES,
    max_leads: int = 1_000_000,
    max_review_items: int = 1_000_000,
) -> MarketShardResult:
    """Acquire and profile one deterministic market shard without Noco access."""

    if not isinstance(shard, MarketSourceShard):
        raise TypeError("shard must be MarketSourceShard")
    if (
        isinstance(max_source_bytes, bool)
        or not isinstance(max_source_bytes, int)
        or not 32 * 1024 * 1024 <= max_source_bytes <= _MAX_SOURCE_BYTES
    ):
        raise ValueError("max_source_bytes is outside the accepted range")

    acquisition = acquire_region(
        _source_region(shard, max_source_bytes),
        cache_dir / "sources",
        timeout_seconds=timeout_seconds,
    )
    extraction: ExtractedPbf | None = None
    local_path = acquisition.local_path
    content_sha256 = acquisition.content_sha256
    size_bytes = acquisition.size_bytes
    provenance = f"checksum-verified Geofabrik source {shard.feature.feature_id}"
    if shard.country_bounds is not None:
        extraction = extract_country_pbf(
            acquisition,
            shard.country_bounds,
            cache_dir / "extracts" / shard.market.country_code.casefold(),
            timeout_seconds=extraction_timeout_seconds,
        )
        local_path = extraction.local_path
        content_sha256 = extraction.content_sha256
        size_bytes = extraction.size_bytes
        provenance = f"bounded country extraction from Geofabrik source {shard.feature.feature_id}"

    registry = builtin_profile_registry()
    definition = registry.get(_MARKET_PROFILE)
    limits = PbfParseLimits(
        max_file_size_bytes=max_source_bytes,
        max_objects=100_000_000,
        max_total_tags=500_000_000,
        max_tags_per_object=512,
        max_blob_size_bytes=32 * 1024 * 1024,
        max_uncompressed_blob_bytes=32 * 1024 * 1024,
        max_total_uncompressed_bytes=16 * 1024 * 1024 * 1024,
        max_blob_count=500_000,
    )
    report = run_profile_shadow(
        approved_input=VerifiedPbfInput(
            local_path=local_path,
            content_sha256=content_sha256,
            size_bytes=size_bytes,
            provenance=provenance,
        ),
        parser=OsmiumPbfParser(limits),
        evaluator=ProfileEvaluator(registry),
        definition=definition,
        region_id=shard.market.country_code.casefold(),
        normalization_context=NormalizationContext(
            country_code=shard.market.country_code,
            calling_code=shard.market.calling_code,
        ),
        max_leads=max_leads,
        max_review_items=max_review_items,
        verify_unique_objects=False,
    )
    return MarketShardResult(
        shard.market,
        shard,
        acquisition,
        extraction,
        report,
    )


__all__ = ["MarketShardResult", "run_market_shard"]
