#!/usr/bin/env python3
"""
build_summary.py
=================
Populates Path_Profile_Summary.csv using:
  - ATT_Network.csv (path list, Path_Length in km)
  - output/tables/<Path_ID2>.csv (per-path elevation profile + source counts)
  - fcc_antennas.csv / fcc_paths.csv (main/diversity antenna heights AGL)

For each path (matched to ATT_Network.csv rows in order, "Path Number" 1, 2, 3...):
  - A/B Site Elev AMSL: ground surface elevation at the first/last sample
    point in the path's table CSV
  - A/B Main/Diversity Ant Height AGL: from FCC PA.dat-based matching
    (same logic as path_profile_tool.py)
  - A/B Main/Diversity Ant Height AMSL: ground elev + AGL
  - Path Length (Miles): converted from Path_Length (km) in ATT_Network.csv
  - USGS 1M / GLO 30 / Total Points: source counts from the table CSV

Usage:
    python build_summary.py ATT_Network.csv Path_Profile_Summary.csv ^
        --out Path_Profile_Summary_filled.csv [--all]

By default, only fills as many rows as the template already has (matching
the first N paths in ATT_Network.csv, in order). Use --all to generate a
full summary for every path in ATT_Network.csv instead.
"""
import argparse
import csv
import math
import os

from path_profile_tool import load_fcc_data, find_path_antennas


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("network_csv")
    ap.add_argument("template_csv")
    ap.add_argument("--out", default="Path_Profile_Summary_filled.csv")
    ap.add_argument("--tables-dir", default="output/tables")
    ap.add_argument("--fcc-antennas", default="fcc_antennas.csv")
    ap.add_argument("--fcc-paths", default="fcc_paths.csv")
    ap.add_argument("--all", action="store_true",
                     help="generate rows for ALL paths in ATT_Network.csv, "
                          "not just as many as the template has")
    args = ap.parse_args()

    with open(args.network_csv, newline="") as f:
        net_rows = [r for r in csv.DictReader(f) if r.get("Ref_ID", "").strip().isdigit()]

    with open(args.template_csv, newline="", encoding="utf-8-sig") as f:
        reader = csv.reader(f)
        header = next(reader)
        template_rows = list(reader)

    n = len(net_rows) if args.all else len(template_rows)
    if n > len(net_rows):
        n = len(net_rows)

    fcc_data = load_fcc_data(args.fcc_antennas, args.fcc_paths)

    out_rows = []
    missing_tables = []
    for i in range(n):
        row = net_rows[i]
        path_id2 = row["Path_ID2"]
        name_a = row["Site_A_Call_Sign"]
        name_b = row["Site_B_Call_Sign"]

        table_path = os.path.join(args.tables_dir, path_id2 + ".csv")
        a_elev = b_elev = None
        n_usgs = n_glo = n_total = 0
        if os.path.exists(table_path):
            with open(table_path, newline="") as f:
                trows = list(csv.DictReader(f))
            n_total = len(trows)
            n_usgs = sum(1 for r in trows if r.get("source") == "usgs_1m")
            n_glo = sum(1 for r in trows if r.get("source") == "glo30")
            if trows:
                try:
                    a_elev = float(trows[0]["Z_surface_elev_m"])
                except (ValueError, KeyError):
                    a_elev = None
                try:
                    b_elev = float(trows[-1]["Z_surface_elev_m"])
                except (ValueError, KeyError):
                    b_elev = None
        else:
            missing_tables.append(path_id2)

        main_a, div_a, main_b, div_b = find_path_antennas(name_a, name_b, fcc_data)

        def agl(ant):
            return ant["antenna_height_agl_m"] if ant else None

        def amsl(ground, ant):
            if ant is None or ground is None or math.isnan(ground):
                return None
            return ground + ant["antenna_height_agl_m"]

        path_length_km = row.get("Path_Length", "").strip()
        path_length_mi = (float(path_length_km) / 1.60934) if path_length_km else None

        def fmt(x, nd=2):
            return "" if x is None else f"{x:.{nd}f}"

        def make_model(ant):
            if ant is None:
                return "", ""
            return ant.get("antenna_make", ""), ant.get("antenna_model", "")

        a_main_make, a_main_model = make_model(main_a)
        a_div_make, a_div_model = make_model(div_a)
        b_main_make, b_main_model = make_model(main_b)
        b_div_make, b_div_model = make_model(div_b)

        out_rows.append([
            i + 1, path_id2,
            name_a, fmt(a_elev), fmt(agl(main_a)), fmt(agl(div_a)),
            fmt(amsl(a_elev, main_a)), fmt(amsl(a_elev, div_a)),
            a_main_make, a_main_model, a_div_make, a_div_model,
            name_b, fmt(b_elev), fmt(agl(main_b)), fmt(agl(div_b)),
            fmt(amsl(b_elev, main_b)), fmt(amsl(b_elev, div_b)),
            b_main_make, b_main_model, b_div_make, b_div_model,
            fmt(path_length_mi, 3),
            n_usgs, n_glo, n_total,
        ])

    with open(args.out, "w", newline="") as f:
        w = csv.writer(f)
        w.writerow(header)
        w.writerows(out_rows)

    print(f"Wrote {len(out_rows)} row(s) to {args.out}")
    if missing_tables:
        print(f"  {len(missing_tables)} path(s) had no table CSV in {args.tables_dir}: "
              f"{', '.join(missing_tables[:10])}" + (" ..." if len(missing_tables) > 10 else ""))


if __name__ == "__main__":
    main()
