"""
Tile Server API Endpoints
Serves Vector Tiles from PMTiles or generates on-demand from PostGIS
"""
from fastapi import APIRouter, HTTPException, Path, Query, Response
from fastapi.responses import JSONResponse
import structlog

from config import settings
from services.tile_server import TileServerService

logger = structlog.get_logger(__name__)
router = APIRouter()

# Initialize tile server service
tile_service = TileServerService()


@router.get("/{z}/{x}/{y}.pbf", response_class=Response)
async def get_vector_tile(
    z: int = Path(..., ge=0, le=22, description="Zoom level"),
    x: int = Path(..., ge=0, description="Tile X coordinate"),
    y: int = Path(..., ge=0, description="Tile Y coordinate"),
):
    """
    Get a vector tile in Protocol Buffers format.

    Returns OSM data as vector tiles suitable for MapLibre GL JS.
    Tiles are served from pre-generated PMTiles or cached on-demand.
    """
    try:
        tile_data = await tile_service.get_tile(z, x, y)

        if tile_data is None:
            # Return empty tile (204 No Content is standard for empty tiles)
            return Response(status_code=204)

        return Response(
            content=tile_data,
            media_type="application/x-protobuf",
            headers={
                "Content-Encoding": "gzip",
                "Cache-Control": "public, max-age=86400",  # 24h cache
                "X-Tile-Source": "pmtiles",
            },
        )

    except FileNotFoundError:
        logger.warning("PMTiles file not found", z=z, x=x, y=y)
        raise HTTPException(
            status_code=503,
            detail="Tile data not available. Please run the data download script first.",
        )
    except Exception as e:
        logger.error("Error serving tile", z=z, x=x, y=y, error=str(e))
        raise HTTPException(status_code=500, detail="Error serving tile")


@router.get("/style.json")
async def get_maplibre_style(
    base_url: str = Query(None, description="Base URL for tile server"),
):
    """
    Get MapLibre GL JS style specification.

    Returns a style document configured for the self-hosted tile server.
    """
    # Use provided base_url or construct from settings
    if base_url is None:
        base_url = f"http://localhost:{settings.port}"

    style = {
        "version": 8,
        "name": "GeoEdu Germany",
        "metadata": {
            "description": "Self-hosted OSM tiles for DSGVO-compliant education",
            "attribution": "© OpenStreetMap contributors",
        },
        "sources": {
            "osm": {
                "type": "vector",
                "tiles": [f"{base_url}/api/v1/tiles/{{z}}/{{x}}/{{y}}.pbf"],
                "minzoom": 0,
                "maxzoom": 14,
                "attribution": "© OpenStreetMap contributors (ODbL)",
            },
            "terrain": {
                "type": "raster-dem",
                "tiles": [f"{base_url}/api/v1/terrain/{{z}}/{{x}}/{{y}}.png"],
                "tileSize": 256,
                "maxzoom": 14,
                "attribution": "© Copernicus DEM GLO-30",
            },
        },
        "sprite": "",
        "glyphs": "https://fonts.openmaptiles.org/{fontstack}/{range}.pbf",
        "layers": [
            # Background
            {
                "id": "background",
                "type": "background",
                "paint": {"background-color": "#f8f4f0"},
            },
            # Water
            {
                "id": "water",
                "type": "fill",
                "source": "osm",
                "source-layer": "water",
                "paint": {"fill-color": "#a0c8f0"},
            },
            # Landuse - Parks
            {
                "id": "landuse-park",
                "type": "fill",
                "source": "osm",
                "source-layer": "landuse",
                "filter": ["==", "class", "park"],
                "paint": {"fill-color": "#c8e6c8", "fill-opacity": 0.5},
            },
            # Landuse - Forest
            {
                "id": "landuse-forest",
                "type": "fill",
                "source": "osm",
                "source-layer": "landuse",
                "filter": ["==", "class", "wood"],
                "paint": {"fill-color": "#94d294", "fill-opacity": 0.5},
            },
            # Buildings
            {
                "id": "building",
                "type": "fill",
                "source": "osm",
                "source-layer": "building",
                "minzoom": 13,
                "paint": {"fill-color": "#d9d0c9", "fill-opacity": 0.8},
            },
            # Roads - Minor
            {
                "id": "road-minor",
                "type": "line",
                "source": "osm",
                "source-layer": "transportation",
                "filter": ["all", ["==", "$type", "LineString"], ["in", "class", "minor", "service"]],
                "paint": {"line-color": "#ffffff", "line-width": 1},
            },
            # Roads - Major
            {
                "id": "road-major",
                "type": "line",
                "source": "osm",
                "source-layer": "transportation",
                "filter": ["all", ["==", "$type", "LineString"], ["in", "class", "primary", "secondary", "tertiary"]],
                "paint": {"line-color": "#ffc107", "line-width": 2},
            },
            # Roads - Highway
            {
                "id": "road-highway",
                "type": "line",
                "source": "osm",
                "source-layer": "transportation",
                "filter": ["all", ["==", "$type", "LineString"], ["==", "class", "motorway"]],
                "paint": {"line-color": "#ff6f00", "line-width": 3},
            },
            # Place labels
            {
                "id": "place-label",
                "type": "symbol",
                "source": "osm",
                "source-layer": "place",
                "layout": {
                    "text-field": "{name}",
                    "text-font": ["Open Sans Regular"],
                    "text-size": 12,
                },
                "paint": {"text-color": "#333333", "text-halo-color": "#ffffff", "text-halo-width": 1},
            },
        ],
        "terrain": {"source": "terrain", "exaggeration": 1.5},
    }

    return JSONResponse(content=style)


@router.get("/metadata")
async def get_tile_metadata():
    """
    Get metadata about available tiles.

    Returns information about data coverage, zoom levels, and update status.
    """
    metadata = await tile_service.get_metadata()

    return {
        "name": "GeoEdu Germany Tiles",
        "description": "Self-hosted OSM vector tiles for Germany",
        "format": "pbf",
        "scheme": "xyz",
        "minzoom": metadata.get("minzoom", 0),
        "maxzoom": metadata.get("maxzoom", 14),
        "bounds": metadata.get("bounds", [5.87, 47.27, 15.04, 55.06]),  # Germany bbox
        "center": metadata.get("center", [10.45, 51.16, 6]),  # Center of Germany
        "attribution": "© OpenStreetMap contributors (ODbL)",
        "data_available": metadata.get("data_available", False),
        "last_updated": metadata.get("last_updated"),
    }


@router.get("/bounds")
async def get_tile_bounds():
    """
    Get the geographic bounds of available tile data.

    Returns bounding box for Germany in [west, south, east, north] format.
    """
    return {
        "bounds": [5.87, 47.27, 15.04, 55.06],  # Germany bounding box
        "center": [10.45, 51.16],
        "description": "Germany (Deutschland)",
    }
