from __future__ import annotations

import importlib.util
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path
from types import SimpleNamespace


ROOT = Path(__file__).resolve().parents[3]
SCRIPT = ROOT / "scripts" / "ops" / "docker-disk-pressure-retention-cleanup.py"
spec = importlib.util.spec_from_file_location("docker_disk_pressure_retention_cleanup", SCRIPT)
module = importlib.util.module_from_spec(spec)
assert spec and spec.loader
sys.modules[spec.name] = module
spec.loader.exec_module(module)


def image(image_id: str, created_at: datetime, tags: tuple[str, ...] = ()):
    return module.ImageInfo(
        image_id=image_id,
        created_at=created_at,
        size_bytes=1024,
        repo_tags=tags,
    )


def test_select_dangling_images_keeps_newest_and_protects_running_images() -> None:
    now = datetime(2026, 7, 1, 12, tzinfo=timezone.utc)
    images = [
        image("sha256:running", now - timedelta(hours=72)),
        image("oldest", now - timedelta(hours=72)),
        image("middle", now - timedelta(hours=48)),
        image("newest", now - timedelta(hours=30)),
        image("too_recent", now - timedelta(hours=2)),
        image("tagged", now - timedelta(hours=72), ("repo:tag",)),
    ]

    selected = module.select_dangling_image_removals(
        images,
        {"running"},
        now=now,
        min_age_hours=24,
        keep_newest=1,
    )

    assert [item.image_id for item in selected] == ["oldest", "middle"]


def test_builder_prune_command_is_bounded_by_age_and_keep_storage() -> None:
    args = SimpleNamespace(
        docker_bin="docker",
        min_age_hours=36,
        builder_keep_storage="40GB",
    )

    assert module.builder_prune_command(args) == [
        "docker",
        "builder",
        "prune",
        "--force",
        "--filter",
        "until=36h",
        "--keep-storage",
        "40GB",
    ]


def test_parse_docker_datetime_accepts_nanosecond_fraction() -> None:
    parsed = module.parse_docker_datetime("2026-07-01T23:29:21.919867918+08:00")

    assert parsed.isoformat() == "2026-07-01T15:29:21.919867+00:00"


def test_summary_never_reports_volumes_or_container_cleanup_boundary() -> None:
    now = datetime(2026, 7, 1, 12, tzinfo=timezone.utc)
    selected = module.select_dangling_image_removals(
        [image("old", now - timedelta(days=3))],
        set(),
        now=now,
        min_age_hours=24,
        keep_newest=0,
    )
    summary = module.summarize_images(selected)

    assert summary["count"] == 1
    assert summary["sample_image_ids"] == ["old"]


def test_cli_exposes_builder_cache_only_flag() -> None:
    help_text = module.run_command(["python3", str(SCRIPT), "--help"]).stdout

    assert "--skip-dangling-images" in help_text


def test_zero_age_builder_prune_omits_until_filter() -> None:
    args = SimpleNamespace(
        docker_bin="docker",
        min_age_hours=0,
        builder_keep_storage="1GB",
    )

    assert module.builder_prune_command(args) == [
        "docker",
        "builder",
        "prune",
        "--force",
        "--keep-storage",
        "1GB",
    ]
