#!/usr/bin/env python3
"""Build one global orthophoto master from tiled orthophoto JPGs."""

from __future__ import annotations

import argparse
import json
from pathlib import Path

from osgeo import gdal


def parse_args() -> argparse.Namespace:
    p = argparse.ArgumentParser(description="Create a global ortho master mosaic from ortho tile JPGs.")
    p.add_argument(
        "--input-dir",
        action="append",
        default=[],
        help="Input directory containing ortho JPG tiles. Can be specified multiple times.",
    )
    p.add_argument("--pattern", default="*.jpg", help="Input filename pattern.")
    p.add_argument("--out-dir", default="work/mask_master", help="Output directory.")
    p.add_argument("--vrt-name", default="ortho_master.vrt", help="Output VRT name.")
    p.add_argument("--tif-name", default="ortho_master.tif", help="Output GeoTIFF name.")
    p.add_argument("--preview-name", default="ortho_master.jpg", help="Output preview JPG name.")
    p.add_argument("--no-preview", action="store_true", help="Skip preview JPG generation.")
    p.add_argument(
        "--preview-max-size",
        type=int,
        default=8192,
        help="Longest preview edge in pixels (aspect preserved).",
    )
    p.add_argument(
        "--compress",
        default="LZW",
        help="GeoTIFF compression (e.g., LZW, DEFLATE, JPEG, NONE).",
    )
    p.add_argument("--resample", default="nearest", help="Resample algorithm for preview (nearest|bilinear|cubic...).")
    return p.parse_args()


def collect_inputs(input_dirs: list[str], pattern: str) -> list[Path]:
    dirs = [Path(d) for d in input_dirs] if input_dirs else [Path("export_unity/ortho_jpg")]
    files: list[Path] = []
    for d in dirs:
        if not d.exists():
            print(f"[ortho_build_master] Warning: input dir missing: {d}")
            continue
        for f in sorted(d.glob(pattern)):
            if f.suffix.lower() != ".jpg":
                continue
            files.append(f)
    return files


def preview_size(width: int, height: int, max_edge: int) -> tuple[int, int]:
    if width <= 0 or height <= 0:
        return width, height
    edge = max(width, height)
    if edge <= max_edge:
        return width, height
    scale = max_edge / float(edge)
    return max(1, int(round(width * scale))), max(1, int(round(height * scale)))


def main() -> int:
    args = parse_args()
    gdal.UseExceptions()

    inputs = collect_inputs(args.input_dir, args.pattern)
    if not inputs:
        raise SystemExit("[ortho_build_master] No input ortho tiles found.")

    out_dir = Path(args.out_dir)
    out_dir.mkdir(parents=True, exist_ok=True)
    vrt_path = out_dir / args.vrt_name
    tif_path = out_dir / args.tif_name
    preview_path = out_dir / args.preview_name
    meta_path = out_dir / "ortho_master_meta.json"

    print(f"[ortho_build_master] Input tiles: {len(inputs)}")
    print(f"[ortho_build_master] Building VRT: {vrt_path}")
    vrt = gdal.BuildVRT(str(vrt_path), [str(p) for p in inputs])
    if vrt is None:
        raise SystemExit("[ortho_build_master] gdal.BuildVRT failed.")

    width = vrt.RasterXSize
    height = vrt.RasterYSize
    gt = vrt.GetGeoTransform(can_return_null=True)
    proj = vrt.GetProjectionRef()

    print(f"[ortho_build_master] Translating GeoTIFF: {tif_path}")
    tif_ds = gdal.Translate(
        str(tif_path),
        vrt,
        options=gdal.TranslateOptions(
            format="GTiff",
            creationOptions=[
                "TILED=YES",
                f"COMPRESS={args.compress}",
                "BIGTIFF=IF_SAFER",
            ],
        ),
    )
    if tif_ds is None:
        raise SystemExit("[ortho_build_master] gdal.Translate to GeoTIFF failed.")
    tif_ds = None

    if not args.no_preview:
        out_w, out_h = preview_size(width, height, args.preview_max_size)
        print(f"[ortho_build_master] Writing preview JPG: {preview_path} ({out_w}x{out_h})")
        jpg_ds = gdal.Translate(
            str(preview_path),
            vrt,
            options=gdal.TranslateOptions(
                format="JPEG",
                width=out_w,
                height=out_h,
                resampleAlg=args.resample,
                creationOptions=["QUALITY=92"],
            ),
        )
        if jpg_ds is None:
            raise SystemExit("[ortho_build_master] gdal.Translate to JPEG preview failed.")
        jpg_ds = None

    vrt = None

    meta = {
        "schema_version": 1,
        "inputs": [str(p) for p in inputs],
        "outputs": {
            "vrt": str(vrt_path),
            "tif": str(tif_path),
            "preview": None if args.no_preview else str(preview_path),
        },
        "raster": {
            "width": width,
            "height": height,
            "geotransform": list(gt) if gt else None,
            "projection": proj,
        },
        "settings": {
            "compress": args.compress,
            "preview_max_size": args.preview_max_size,
            "resample": args.resample,
            "pattern": args.pattern,
            "input_dirs": args.input_dir if args.input_dir else ["export_unity/ortho_jpg"],
        },
    }
    meta_path.write_text(json.dumps(meta, indent=2), encoding="utf-8")
    print(f"[ortho_build_master] Wrote metadata: {meta_path}")
    return 0


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

