"""Check an existing output directory's free-space budget without writing files."""
import argparse
import json
from pathlib import Path
import shutil
import sys

MIB = 1024 * 1024


def nonnegative_int(text):
    value = int(text)
    if value < 0:
        raise argparse.ArgumentTypeError("must be a nonnegative integer")
    return value


def budget_report(directory, need_mib, reserve_mib):
    directory = Path(directory).resolve(strict=True)
    if not directory.is_dir():
        raise NotADirectoryError(f"not a directory: {directory}")
    free = shutil.disk_usage(directory).free
    required = (need_mib + reserve_mib) * MIB
    return {
        "path": str(directory),
        "free_bytes": free,
        "required_bytes": required,
        "shortfall_bytes": max(0, required - free),
        "ok": free >= required,
    }


def main(argv=None):
    parser = argparse.ArgumentParser(description=__doc__, allow_abbrev=False)
    parser.add_argument("directory", type=Path, help="existing output directory")
    parser.add_argument("--need-mib", type=nonnegative_int, required=True,
                        help="estimated peak additional space in MiB")
    parser.add_argument("--reserve-mib", type=nonnegative_int, default=1024,
                        help="space to leave free in MiB (default: 1024)")
    args = parser.parse_args(argv)
    try:
        report = budget_report(args.directory, args.need_mib, args.reserve_mib)
    except (OSError, RuntimeError) as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 2
    print(json.dumps(report, ensure_ascii=False))
    return 0 if report["ok"] else 1


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