"""
JSON API endpoints for interactive maps.

Serves pre-aggregated geographic data from analytics.duckdb for Leaflet maps.
All responses are JSON with 1-hour public cache headers (data changes at most
daily when the pipeline runs).
"""
from quart import Blueprint, abort, jsonify

from .analytics import fetch_analytics
from .auth.routes import login_required
from .core import fetch_all, is_flag_enabled

bp = Blueprint("api", __name__)

_CACHE_HEADERS = {"Cache-Control": "public, max-age=3600"}


async def _require_maps_flag() -> None:
    """Abort with 404 if the maps feature flag is explicitly disabled.

    Defaults to enabled (True) so that dev environments without the flag row
    in the DB still work. An admin can disable by setting the flag to False.
    """
    if not await is_flag_enabled("maps", default=True):
        abort(404)


@bp.route("/markets/countries.json")
@login_required
async def countries():
    """Country-level aggregates for the markets hub map."""
    await _require_maps_flag()
    rows = await fetch_analytics("""
        SELECT country_code, country_name_en, country_slug,
               COUNT(*) AS city_count,
               SUM(city_padel_venue_count) AS total_venues,
               ROUND(AVG(market_score), 1) AS avg_market_score,
               ROUND(AVG(opportunity_score), 1) AS avg_opportunity_score,
               AVG(lat) AS lat, AVG(lon) AS lon
        FROM serving.location_profiles
        WHERE city_slug IS NOT NULL
        GROUP BY country_code, country_name_en, country_slug
        HAVING SUM(city_padel_venue_count) > 0
        ORDER BY total_venues DESC
    """)
    return jsonify(rows), 200, _CACHE_HEADERS


@bp.route("/markets/<country_slug>/cities.json")
@login_required
async def country_cities(country_slug: str):
    """City-level data for a country overview bubble map."""
    await _require_maps_flag()
    assert country_slug, "country_slug required"
    rows = await fetch_analytics(
        """
        SELECT city_name, city_slug, lat, lon,
               city_padel_venue_count AS padel_venue_count,
               market_score, opportunity_score, population
        FROM serving.location_profiles
        WHERE country_slug = ? AND city_slug IS NOT NULL
        ORDER BY city_padel_venue_count DESC
        LIMIT 200
        """,
        [country_slug],
    )
    # Check which cities have published articles (any language).
    article_rows = await fetch_all(
        """SELECT url_path FROM articles
           WHERE url_path LIKE ? AND status = 'published'
           AND published_at <= datetime('now')""",
        (f"/markets/{country_slug}/%",),
    )
    article_slugs = set()
    for a in article_rows:
        parts = a["url_path"].rstrip("/").split("/")
        if len(parts) >= 4:
            article_slugs.add(parts[3])
    for row in rows:
        row["has_article"] = row["city_slug"] in article_slugs
    return jsonify(rows), 200, _CACHE_HEADERS


@bp.route("/markets/<country_slug>/<city_slug>/venues.json")
async def city_venues(country_slug: str, city_slug: str):
    """Venue-level dots for the city detail map."""
    await _require_maps_flag()
    assert country_slug and city_slug, "country_slug and city_slug required"
    rows = await fetch_analytics(
        """
        SELECT name, lat, lon, court_count,
               indoor_court_count, outdoor_court_count
        FROM serving.city_venue_locations
        WHERE country_slug = ? AND city_slug = ?
        LIMIT 500
        """,
        [country_slug, city_slug],
    )
    return jsonify(rows), 200, _CACHE_HEADERS

