"""Příkazová řádka Babofkátoru."""
from __future__ import annotations

import argparse
import json
import os
import sys

from . import __version__
from .pipeline import Params, run, export


def build_parser():
    ap = argparse.ArgumentParser(
        prog="babofkator",
        description="Korekce podkosů/úkosů STL reliéfu a tvorba inverzní "
                    "jednodílné formy s lemem.",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    ap.add_argument("input",
                    help="vstupní model STL / OBJ / ASCII PLY "
                         "(reliéf nad dělící rovinou)")
    ap.add_argument("-o", "--out", default="vystup", help="výstupní adresář")
    ap.add_argument("--name", default=None, help="základ názvu výstupů")

    ap.add_argument("-d", "--draft", type=float, default=3.0,
                    metavar="STUPNE",
                    help="požadovaný úhel úkosu (odklon stěny od osy vyjmutí)")
    ap.add_argument("-w", "--wall", type=float, default=3.0,
                    help="tloušťka stěny formy v mm")
    ap.add_argument("-r", "--rim", type=float, default=5.0,
                    help="šířka lemu v mm")
    ap.add_argument("--res", type=float, default=0.0,
                    help="rozlišení mřížky v mm (0 = automaticky)")
    ap.add_argument("--cells", type=int, default=1200,
                    help="cílový počet buněk na delší straně (auto rozlišení)")
    ap.add_argument("--mode", choices=["add", "cut", "balanced"], default="add",
                    help="korekce přidáním / ubráním / vyvážená")
    ap.add_argument("--back", choices=["shell", "flat"], default="shell",
                    help="hřbet formy: kopírující plášť nebo rovný")
    ap.add_argument("--rim-smooth", type=float, default=-1.0,
                    help="zjednodušení obrysu lemu v mm (-1 = jako šířka lemu, "
                         "0 = přesně podle siluety)")
    ap.add_argument("--up", choices=["auto", "z", "y", "x"], default="auto",
                    help="osa vyjmutí odlitku")
    ap.add_argument("--smooth", type=float, default=0.0,
                    help="vyhlazení přechodů v pixelech (0 = vypnuto)")
    ap.add_argument("--plane", type=float, default=None,
                    help="souřadnice Z dělící roviny (výchozí: min Z modelu)")
    ap.add_argument("--no-model", action="store_true",
                    help="negenerovat korigovaný model")
    ap.add_argument("--no-mold", action="store_true",
                    help="negenerovat formu")
    ap.add_argument("--png", action="store_true",
                    help="uložit i náhledové mapy (vyžaduje matplotlib)")
    ap.add_argument("-q", "--quiet", action="store_true")
    ap.add_argument("-V", "--version", action="version",
                    version=f"Babofkátor {__version__}")
    return ap


def main(argv=None):
    args = build_parser().parse_args(argv)
    p = Params(draft_deg=args.draft, wall_mm=args.wall, rim_mm=args.rim,
               resolution_mm=args.res, target_cells=args.cells,
               mode=args.mode, back=args.back, smooth_px=args.smooth,
               rim_smooth_mm=args.rim_smooth, up_axis=args.up,
               plane_z=args.plane,
               make_model=not args.no_model, make_mold=not args.no_mold)

    def prog(pct, msg):
        if not args.quiet:
            print(f"[{pct:3d}%] {msg}", file=sys.stderr, flush=True)

    res = run(args.input, p, progress=prog)
    stem = args.name or os.path.splitext(os.path.basename(args.input))[0]
    paths = export(res, args.out, stem)

    rep_path = os.path.join(args.out, f"{stem}_protokol.json")
    with open(rep_path, "w", encoding="utf-8") as fh:
        json.dump({"params": res.params, "report": res.report}, fh,
                  ensure_ascii=False, indent=2, default=str)
    paths["report"] = rep_path

    if args.png:
        from .preview import make_maps
        import base64
        maps = make_maps(res)
        for k, v in maps.items():
            pth = os.path.join(args.out, f"{stem}_{k}.png")
            with open(pth, "wb") as fh:
                fh.write(base64.b64decode(v.split(",", 1)[1]))
            paths[k] = pth

    if not args.quiet:
        r = res.report
        print("\n=== Babofkátor — souhrn ===")
        print(f"Vstup            : {args.input}  "
              f"({r['input']['n_faces']} trojúhelníků)")
        print(f"Osa vyjmutí      : {r['input']['up_axis'].upper()}")
        print(f"Rozměr           : "
              f"{r['input']['size_mm'][0]:.2f} × {r['input']['size_mm'][1]:.2f}"
              f" × {r['input']['size_mm'][2]:.2f} mm")
        print(f"Mřížka           : {r['grid']['nx']}×{r['grid']['ny']} px, "
              f"krok {r['grid']['res_mm']:.3f} mm")
        u = r["undercuts"]
        print(f"Podkosy (lokálně): {u['local_undercut_faces']} stěn, "
              f"{u['local_undercut_area_pct']:.1f} % plochy")
        print(f"Malý úkos        : {u['insufficient_draft_area_pct']:.1f} % plochy")
        print(f"Zaplněno obálkou : {u['volume_filled_by_envelope_mm3']:.1f} mm³")
        c = r["correction"]
        print(f"Korekce ({c['mode']:8s}): +{c['material_added_mm3']:.1f} / "
              f"-{c['material_removed_mm3']:.1f} mm³, dotčeno "
              f"{c['changed_area_pct']:.2f} % plochy")
        print(f"Dosažený úkos    : {c['achieved_min_draft_deg']:.3f}° "
              f"(požadavek {c['required_draft_deg']}°)")
        if r["mold"]:
            print(f"Forma            : výška {r['mold']['mold_height_mm']:.2f} mm, "
                  f"min. tloušťka stěny {r['mold']['min_wall_mm']:.2f} mm, "
                  f"lem {args.rim} mm")
        for k, v in r["mesh_checks"].items():
            if v:
                print(f"Kontrola {k:6s}  : vodotěsný={v['watertight']}, "
                      f"manifold={v['n_nonmanifold_edges'] == 0}, "
                      f"orientace={v['consistent_orientation']}, "
                      f"objem={v['volume_mm3']:.1f} mm³")
        print("\nVýstupy:")
        for k, v in paths.items():
            print(f"  {k:8s} {v}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
