"""
Structured return types for Yoro operations.

Pure Python dataclasses — no external dependencies.
"""

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True, slots=True)
class Bounds:
    """Geographic bounding box of a Hilbert cell."""

    lat_min: float
    lat_max: float
    lon_min: float
    lon_max: float

    def as_dict(self) -> dict[str, float]:
        return {
            "lat_min": self.lat_min,
            "lat_max": self.lat_max,
            "lon_min": self.lon_min,
            "lon_max": self.lon_max,
        }

    def as_bbox_tuple(self) -> tuple[float, float, float, float]:
        """Return ``(lon_min, lat_min, lon_max, lat_max)`` — standard GIS order."""
        return (self.lon_min, self.lat_min, self.lon_max, self.lat_max)


@dataclass(frozen=True, slots=True)
class EncodeResult:
    """Result of encoding GPS coordinates."""

    code: str
    lat: float
    lon: float
    precision: int
    domain: str
    resolution_m: float
    bounds: Bounds


@dataclass(frozen=True, slots=True)
class DecodeResult:
    """Result of decoding an Yoro string."""

    code: str
    lat: float
    lon: float
    precision: int
    domain: str
    resolution_m: float
    bounds: Bounds
    neighbors: list[str]


@dataclass(frozen=True, slots=True)
class PrecisionLevel:
    """A canonical precision level — one that produces a distinct grid.

    Due to base-29 quantization, not every Hilbert order *p* yields a new
    code length.  Only canonical precisions create distinct grids.  Asking
    for a non-canonical *p* silently snaps to the nearest canonical one.
    """

    precision: int
    """Effective Hilbert order (grid is 2^p x 2^p)."""

    code_length: int
    """Number of base-29 characters after the domain prefix."""

    grid_size: int
    """Number of cells per axis (``2 ** precision``)."""

    total_cells: int
    """Total number of cells in the domain (``grid_size ** 2``)."""

    resolution_m: float
    """Approximate cell size in meters for the given domain."""


@dataclass(frozen=True, slots=True)
class DomainInfo:
    """Metadata about a geographic domain."""

    code: str
    name: str
    bounds: Bounds
