# retoor <retoor@molodetz.nl>

from devplacepy.cli._shared import _audit_cli


def _human(n):
    n = float(n)
    for unit in ("B", "KB", "MB", "GB", "TB"):
        if n < 1024:
            return f"{n:.1f}{unit}"
        n /= 1024
    return f"{n:.1f}PB"


def cmd_system_prune(args):
    from devplacepy.attachments import (
        purge_soft_deleted_attachments,
        sweep_orphan_attachment_blobs,
    )
    from devplacepy.project_files import (
        purge_soft_deleted_project_files,
        sweep_orphan_project_file_blobs,
    )
    from devplacepy.services.containers import store as container_store

    dry_run = bool(args.dry_run)
    verb = "Would remove" if dry_run else "Removed"

    totals = {"items": 0, "freed": 0}

    def report(name, count, freed):
        totals["items"] += count
        totals["freed"] += freed
        print(f"  {name}: {verb.lower()} {count} item(s), {_human(freed)}")

    print("System prune - safe but aggressive disk-space cleanup")
    print(
        "Removes only content with zero live reference: soft-deleted attachment/"
        "\nproject-file blobs, and blob files with no matching database row at all"
        "\n(orphans, e.g. left behind by an interrupted or racing sync). Never"
        "\ntouches live content."
    )
    if dry_run:
        print("DRY RUN: nothing will be deleted.")
    print()

    count, freed = purge_soft_deleted_attachments(dry_run=dry_run)
    report("soft-deleted attachments", count, freed)

    count, freed = purge_soft_deleted_project_files(dry_run=dry_run)
    report("soft-deleted project files", count, freed)

    count, freed = sweep_orphan_attachment_blobs(dry_run=dry_run)
    report("orphan attachment blobs", count, freed)

    count, freed = sweep_orphan_project_file_blobs(dry_run=dry_run)
    report("orphan project-file blobs", count, freed)

    removed = container_store.gc_workspaces(dry_run=dry_run)
    totals["items"] += removed
    plural = "y" if removed == 1 else "ies"
    print(f"  orphaned container workspaces: {verb.lower()} {removed} director{plural}")

    print()
    suffix = " (estimate)" if dry_run else ""
    print(f"{verb} {totals['items']} item(s) total, {_human(totals['freed'])} of disk{suffix}")

    if not dry_run:
        _audit_cli(
            "cli.system.prune",
            f"CLI system prune removed {totals['items']} item(s), freed {_human(totals['freed'])}",
            metadata={"items": totals["items"], "bytes_freed": totals["freed"]},
        )


def register_system(subparsers):
    system = subparsers.add_parser("system", help="Cross-cutting system maintenance")
    system_sub = system.add_subparsers(title="action", dest="action")
    prune = system_sub.add_parser(
        "prune",
        help=(
            "Safe but aggressive disk-space cleanup: purges soft-deleted "
            "attachment/project-file blobs and any blob with zero database "
            "reference at all, plus orphaned container workspace directories"
        ),
    )
    prune.add_argument(
        "--dry-run",
        action="store_true",
        help="Report what would be removed without deleting anything",
    )
    prune.set_defaults(func=cmd_system_prune)
