"""..title :: Watch By County Shapefile Export

Return to `API Services </api/#cgi>`_

Changelog
---------

- 2026-01-01: A bug was fixed with the resulting download zip file name.

Example Requests
----------------

Return the watch by county shapefile for watch 275 at 17 UTC on 21 May 2024

https://mesonet.agron.iastate.edu/cgi-bin/request/gis/watch_by_county.py?\
etn=275&year=2024&month=5&day=21&hour=17&minute=0

"""

import tempfile
import zipfile
from io import BytesIO

from osgeo import ogr
from pyiem.exceptions import IncompleteWebRequest
from pyiem.util import utc
from pyiem.webutil import CGIModel, iemapp

from iemweb.fields import (
    DAY_OF_MONTH_FIELD_OPTIONAL,
    HOUR_FIELD_OPTIONAL,
    MINUTE_FIELD_OPTIONAL,
    MONTH_FIELD_OPTIONAL,
    VTEC_ETN_FIELD_OPTIONAL,
    YEAR_FIELD_OPTIONAL,
)

ogr.UseExceptions()
PROJFILE = "/opt/iem/data/gis/meta/4326.prj"


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

    etn: VTEC_ETN_FIELD_OPTIONAL = None
    year: YEAR_FIELD_OPTIONAL = None
    month: MONTH_FIELD_OPTIONAL = None
    day: DAY_OF_MONTH_FIELD_OPTIONAL = None
    hour: HOUR_FIELD_OPTIONAL = None
    minute: MINUTE_FIELD_OPTIONAL = None


def get_ts_fn(environ):
    """Figure out what is requested."""
    # Get CGI vars
    if environ["year"] is not None:
        ts = utc(
            environ["year"],
            environ["month"],
            environ["day"],
            environ["hour"],
            environ["minute"],
        )
        fn = f"watch_by_county_{ts:%Y%m%d%H%M}"
    else:
        ts = utc()
        fn = "watch_by_county"
    return ts, fn


@iemapp(help=__doc__, schema=Schema)
def application(environ, start_response):
    """Go Main Go"""
    try:
        ts, fn = get_ts_fn(environ)
    except Exception as exp:
        raise IncompleteWebRequest("bad input provided") from exp
    if environ["etn"] is not None:
        etnLimiter = f"and eventid = {int(environ.get('etn'))}"
    else:
        etnLimiter = ""

    with tempfile.TemporaryDirectory() as tmpdir:
        table = f"warnings_{ts.year}"
        source = ogr.Open(
            "PG:host=iemdb-postgis.local dbname=postgis "
            f"user=nobody tables={table}(tgeom)"
        )

        out_driver = ogr.GetDriverByName("ESRI Shapefile")
        out_ds = out_driver.CreateDataSource(f"{tmpdir}/{fn}.shp")
        out_layer = out_ds.CreateLayer("polygon", None, ogr.wkbPolygon)

        fd = ogr.FieldDefn("ISSUED", ogr.OFTString)
        fd.SetWidth(12)
        out_layer.CreateField(fd)

        fd = ogr.FieldDefn("EXPIRED", ogr.OFTString)
        fd.SetWidth(12)
        out_layer.CreateField(fd)

        fd = ogr.FieldDefn("PHENOM", ogr.OFTString)
        fd.SetWidth(2)
        out_layer.CreateField(fd)

        fd = ogr.FieldDefn("SIG", ogr.OFTString)
        fd.SetWidth(1)
        out_layer.CreateField(fd)

        fd = ogr.FieldDefn("ETN", ogr.OFTInteger)
        out_layer.CreateField(fd)

        tt = ts.strftime("%Y-%m-%d %H:%M+00")
        sql = f"""
            select phenomena, eventid, ST_multi(ST_union(u.geom)) as tgeom,
            max(to_char(expire at time zone 'UTC', 'YYYYMMDDHH24MI'))
                as utcexpire,
            min(to_char(issue at time zone 'UTC', 'YYYYMMDDHH24MI'))
                as utcissue
            from warnings w JOIN ugcs u on (u.gid = w.gid)
            WHERE vtec_year = {ts.year} and
            significance = 'A' and phenomena IN ('TO','SV')
            and issue > '{tt}'::timestamp -'3 days':: interval
            and issue <= '{tt}' and
            expire > '{tt}' {etnLimiter}
            GROUP by phenomena, eventid ORDER by phenomena ASC
        """

        data = source.ExecuteSQL(sql)

        while True:
            feat = data.GetNextFeature()
            if not feat:
                break
            geom = feat.GetGeometryRef()

            featDef = ogr.Feature(out_layer.GetLayerDefn())
            featDef.SetGeometry(geom)
            featDef.SetField("PHENOM", feat.GetField("phenomena"))
            featDef.SetField("SIG", "A")
            featDef.SetField("ETN", feat.GetField("eventid"))
            featDef.SetField("ISSUED", feat.GetField("utcissue"))
            featDef.SetField("EXPIRED", feat.GetField("utcexpire"))

            out_layer.CreateFeature(featDef)
            feat.Destroy()

        source.Close()
        out_ds.Close()

        zio = BytesIO()
        with zipfile.ZipFile(
            zio, mode="w", compression=zipfile.ZIP_DEFLATED
        ) as zf:
            with open(PROJFILE, encoding="ascii") as fp:
                zf.writestr(f"{fn}.prj", fp.read())
            for suffix in ("shp", "shx", "dbf"):
                zf.write(f"{tmpdir}/{fn}.{suffix}", f"{fn}.{suffix}")

    headers = [
        ("Content-type", "application/octet-stream"),
        ("Content-Disposition", f"attachment; filename={fn}.zip"),
    ]
    start_response("200 OK", headers)
    return [zio.getvalue()]
