""".. title:: Special Weather Statement (SPS) GeoJSON

Return to `API Services </api/#json>`_ listing.

Documentation for /geojson/sps.py
---------------------------------

This service emits a geojson for a given valid time of NWS Special Weather
Statements (SPS) that contain polygons.

Changelog
---------

- 2025-05-02: Bring all available SPS attributes along for the ride.
- 2024-06-30: Initial documentation release.

Example Usage
-------------

Return up to the moment SPSs with polygons.

https://mesonet.agron.iastate.edu/geojson/sps.py

Return SPSs valid at 20 UTC on 10 August 2024

https://mesonet.agron.iastate.edu/geojson/sps.py?valid=2024-08-10T20:00:00Z

"""

import json
from datetime import datetime
from typing import Annotated

from pydantic import AwareDatetime, Field
from pyiem.database import get_sqlalchemy_conn, sql_helper
from pyiem.reference import ISO8601
from pyiem.util import utc
from pyiem.webutil import CGIModel, iemapp

from iemweb.fields import CALLBACK_FIELD
from iemweb.util import json_response_dict


class Schema(CGIModel):
    """See how we are called."""

    callback: CALLBACK_FIELD = None
    valid: Annotated[
        AwareDatetime,
        Field(
            ge=utc(1980),
            default_factory=utc,
            description="Optional timestamp to request SPSs for.",
        ),
    ]


def run(valid: datetime) -> str:
    """Actually do the hard work of getting the current SPS in geojson"""
    with get_sqlalchemy_conn("postgis") as conn:
        res = conn.execute(
            sql_helper("""
            SELECT ST_asGeoJson(geom) as geojson, product_id,
            issue at time zone 'UTC' as utc_issue,
            expire at time zone 'UTC' as utc_expire, landspout, waterspout,
            max_hail_size, max_wind_gust, segmentnum, wfo
            from sps WHERE issue <= :valid and expire > :valid
            and not ST_IsEmpty(geom) and geom is not null
        """),
            {"valid": valid},
        )
        data = json_response_dict(
            {
                "type": "FeatureCollection",
                "features": [],
                "valid_at": valid.strftime(ISO8601),
            }
        )

        for row in res.mappings():
            sts = row["utc_issue"].strftime(ISO8601)
            ets = row["utc_expire"].strftime(ISO8601)
            href = f"/api/1/nwstext/{row['product_id']}"
            data["features"].append(
                dict(
                    type="Feature",
                    id=row["product_id"],
                    properties={
                        "href": href,
                        "issue": sts,
                        "expire": ets,
                        "landspout": row["landspout"],
                        "waterspout": row["waterspout"],
                        "max_hail_size": row["max_hail_size"],
                        "max_wind_gust": row["max_wind_gust"],
                        "segmentnum": row["segmentnum"],
                        "wfo": row["wfo"],
                    },
                    geometry=json.loads(row["geojson"]),
                )
            )
    data["count"] = len(data["features"])
    return json.dumps(data)


def get_mckey(environ: dict) -> str:
    """Return a memcache key."""
    return f"/geojson/sps.geojson|{environ['valid']:%Y%m%d%H%M}"


@iemapp(
    help=__doc__,
    schema=Schema,
    memcachekey=get_mckey,
    memcacheexpire=15,
    content_type="application/vnd.geo+json",
)
def application(environ: dict, start_response):
    """Do Main"""
    res = run(environ["valid"])
    start_response("200 OK", [("Content-type", "application/vnd.geo+json")])
    return res
