"""Preview or delete old completed .log files in one trusted directory."""
import argparse
import json
import os
from pathlib import Path
import stat
import sys
import time

DAY_NS = 86400 * 1_000_000_000


def positive_days(text):
    try:
        value = int(text)
    except ValueError:
        raise argparse.ArgumentTypeError("days must be an integer") from None
    if not 1 <= value <= 36500:
        raise argparse.ArgumentTypeError("days must be 1..36500")
    return value


def signature(info):
    return (info.st_dev, info.st_ino, info.st_size,
            info.st_mtime_ns, info.st_ctime_ns, info.st_nlink)


def select_logs(root, days, now_ns):
    cutoff = now_ns - days * DAY_NS
    selected = []
    with os.scandir(root) as entries:
        for entry in entries:
            if entry.name.startswith(".") or not entry.name.endswith(".log"):
                continue
            info = entry.stat(follow_symlinks=False)
            if (stat.S_ISREG(info.st_mode) and info.st_nlink == 1
                    and info.st_mtime_ns < cutoff):
                selected.append((root / entry.name, info))
    return sorted(selected, key=lambda item: item[0].name)


def emit(record):
    print(json.dumps(record, ensure_ascii=True), flush=True)


def apply_one(path, previous):
    current = path.lstat()
    if (not stat.S_ISREG(current.st_mode)
            or signature(current) != signature(previous)):
        raise ValueError(f"changed since scan: {path.name!a}")
    path.unlink()


def main():
    parser = argparse.ArgumentParser(description=__doc__, allow_abbrev=False)
    parser.add_argument("directory", type=Path)
    parser.add_argument("--days", required=True, type=positive_days)
    parser.add_argument("--apply", action="store_true",
                        help="delete selected files; default only previews")
    args = parser.parse_args()
    deleted = 0
    try:
        root = args.directory.expanduser().resolve(strict=True)
        if not root.is_dir():
            raise ValueError("directory must be a directory")
        selected = select_logs(root, args.days, time.time_ns())
        for path, info in selected:
            if args.apply:
                apply_one(path, info)
                deleted += 1
            emit({"action": "deleted" if args.apply else "would_delete",
                  "name": path.name, "bytes": info.st_size})
        emit({"mode": "apply" if args.apply else "preview",
              "selected": len(selected), "deleted": deleted})
        return 0
    except (OSError, ValueError) as exc:
        print(f"ERROR: deleted={deleted}; {str(exc)!a}", file=sys.stderr)
        return 1


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