"""
01_download_osm.py
==================
Scarica la rete pedonale OSM che copre TUTTI gli edifici di Parma.

Input:
  - data/path_building_to_pois_all_parma.gpkg  (layer 'footprints_all')

Output:
  - pipeline/_cache/osm_walk_parma.graphml

L'operazione si fa UNA VOLTA SOLA. Tutti gli step successivi (02, 03)
riutilizzano questo grafo. Se il file esiste gia', lo step viene saltato
(rimuovi il file per forzare il ridownload).

Tempo stimato: 30 secondi - 3 minuti (dipende dalla rete).
"""
import os
import time
import geopandas as gpd
import osmnx as ox

import config as C


def main():
    t0 = time.time()
    C.log("=== 01 - Download rete pedonale OSM (Parma) ===", "==")

    if os.path.exists(C.OSM_GRAPHML_FILE):
        C.log(f"Grafo gia' presente in cache: {C.OSM_GRAPHML_FILE}")
        C.log("Skippo. Per forzare il ridownload, elimina il file e rilancia.")
        return

    # ------------------------------------------------------------------
    # 1) Calcolo bbox dagli edifici (in WGS84) + buffer
    # ------------------------------------------------------------------
    C.log(f"Leggo edifici: {C.SOURCE_GPKG} (layer '{C.FOOTPRINTS_LAYER}')")
    fp = gpd.read_file(C.SOURCE_GPKG, layer=C.FOOTPRINTS_LAYER)
    C.log(f"  edifici totali: {len(fp)}  |  crs originale: {fp.crs}")

    # Proietto in metrico per applicare il buffer
    fp_metric = fp.to_crs(C.METRIC_CRS)
    minx, miny, maxx, maxy = fp_metric.total_bounds
    minx -= C.OSM_BUFFER_M;  maxx += C.OSM_BUFFER_M
    miny -= C.OSM_BUFFER_M;  maxy += C.OSM_BUFFER_M

    # Riporto bbox in WGS84 per osmnx
    from shapely.geometry import box
    bbox_metric = gpd.GeoSeries([box(minx, miny, maxx, maxy)], crs=C.METRIC_CRS)
    bbox_wgs    = bbox_metric.to_crs("EPSG:4326").iloc[0]
    west, south, east, north = bbox_wgs.bounds
    C.log(f"  bbox WGS84 (lon/lat) buffer {C.OSM_BUFFER_M:.0f} m:")
    C.log(f"    W={west:.5f}  S={south:.5f}  E={east:.5f}  N={north:.5f}")

    # ------------------------------------------------------------------
    # 2) Download via osmnx
    # ------------------------------------------------------------------
    C.log(f"Scarico rete OSM (network_type='{C.OSM_NETWORK_TYPE}')...")
    C.log("  (puo' richiedere 1-3 minuti; sono ~migliaia di archi)")

    # IMPORTANTE: simplify=False per mantenere la geometria reale degli archi
    # (vertici intermedi che seguono le curve delle strade).
    # In osmnx >= 2.0 la firma corretta e' bbox=(left, bottom, right, top).
    G = ox.graph_from_bbox(
        bbox=(west, south, east, north),
        network_type=C.OSM_NETWORK_TYPE,
        simplify=False,
        retain_all=False,         # tieni solo la componente connessa principale
        truncate_by_edge=True,
    )
    C.log(f"  scaricato: {G.number_of_nodes()} nodi, {G.number_of_edges()} archi")

    # ------------------------------------------------------------------
    # 3) Salvataggio GraphML (verra' ricaricato dagli step 02 e 03)
    # ------------------------------------------------------------------
    C.log(f"Salvo: {C.OSM_GRAPHML_FILE}")
    ox.save_graphml(G, C.OSM_GRAPHML_FILE)

    C.log(f"FATTO in {time.time()-t0:.1f} s", "==")


if __name__ == "__main__":
    main()
