#!/usr/bin/env python3
"""
Download matching T04 files from gnssplot when the 12-digit
YYYYMMDDHHMM in the local filename matches.

Example local names: SUMO2_____202604232100.T04
Remote names:        R750-Strip202604232100.T04
"""

from __future__ import annotations

import argparse
import re
import sys
import urllib.error
import urllib.request
from pathlib import Path


def timestamps_from_dir(directory: Path, pattern: str) -> set[str]:
    """Collect unique 12-char timestamp suffixes (before extension) from each matching file."""
    out: set[str] = set()
    for path in sorted(directory.glob(pattern)):
        if not path.is_file():
            continue
        stem = path.stem
        if len(stem) < 12:
            continue
        out.add(stem[-12:])
    return out


def is_timestamp12(s: str) -> bool:
    return bool(re.fullmatch(r"\d{12}", s))


def download(url: str, dest: Path, timeout: float) -> None:
    dest.parent.mkdir(parents=True, exist_ok=True)
    request = urllib.request.Request(url, headers={"User-Agent": "download_matched/1.0"})
    with urllib.request.urlopen(request, timeout=timeout) as response:
        data = response.read()
    dest.write_bytes(data)


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Download matching .T04 files for timestamps present in local T04 files.",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument(
        "-d", "--directory",
        type=Path,
        default=Path("."),
        help="Directory to scan for local T04 files.",
    )
    parser.add_argument(
        "-p", "--pattern",
        default="*.T04",
        help="Glob for local files (default: *.T04).",
    )
    parser.add_argument(
        "--prefix", default="R750-Strip",
        help="The prefix of the file on the remote server (default: R750-Strip).",
    )
    parser.add_argument(
        "--base-url",
        default="http://gnssplot.eng.trimble.com/GNSS_Data/BASES/WCO_Track_R750",
        help="Base URL of the remote base directory (no trailing slash).",
    )
    parser.add_argument(
        "-n", "--dry-run",
        action="store_true",
        help="List URLs that would be fetched without downloading.",
    )
    parser.add_argument(
        "-f", "--force",
        action="store_true",
        help="Re-download even if the R750 file already exists locally.",
    )
    parser.add_argument(
        "--timeout",
        type=float,
        default=120.0,
        help="Per-request timeout in seconds (default: 120).",
    )
    args = parser.parse_args()
    base = str(args.base_url).rstrip("/")
    directory: Path = args.directory.resolve()

    stamps = timestamps_from_dir(directory, args.pattern)
    bad = [s for s in stamps if not is_timestamp12(s)]
    if bad:
        print("Skipping non-12-digit suffixes: " + ", ".join(sorted(bad)[:20]), file=sys.stderr)
    stamps = {s for s in stamps if is_timestamp12(s)}

    if not stamps:
        print("No matching local timestamps found.", file=sys.stderr)
        return 1

    n_ok = 0
    n_skip = 0
    n_err = 0
    for ts in sorted(stamps):
        name = f"{args.prefix}{ts}.T04"
        url = f"{base}/{name}"
        dest = directory / name
        if dest.exists() and not args.force and not args.dry_run:
            n_skip += 1
            print(f"skip (exists): {name}")
            continue
            
        if args.dry_run:
            print(f"would fetch: {url} -> {dest}")
            n_ok += 1
            continue
            
        try:
            print(f"fetch: {name}", flush=True)
            download(url, dest, args.timeout)
            n_ok += 1
        except urllib.error.HTTPError as e:
            print(f"error: {name} -> HTTP {e.code} {e.reason}", file=sys.stderr)
            n_err += 1
        except (urllib.error.URLError, OSError) as e:
            print(f"error: {name} -> {e}", file=sys.stderr)
            n_err += 1

    print(f"done: fetched={n_ok} skipped_existing={n_skip} failed={n_err} unique_timestamps={len(stamps)}")
    return 0 if n_err == 0 else 2


if __name__ == "__main__":
    raise SystemExit(main())
