package cmd

import (
	"strings"
	"testing"
)

func TestCleanupDryRun(t *testing.T) {
	log := fakeRuntime(t, "podman", fakeEngine)
	app, stdout, _ := testApp(t, nil)

	code := app.Run([]string{"cleanup", "--dry-run"})
	if code != exitOK {
		t.Fatalf("exit = %d", code)
	}
	out := stdout.String()
	if !strings.Contains(out, "would remove container abc123") {
		t.Errorf("dry-run should list the stopped container:\n%s", out)
	}
	if strings.Contains(out, "def456") {
		t.Errorf("running container needs --running:\n%s", out)
	}
	calls := readLog(t, log)
	if strings.Contains(calls, "rm ") || strings.Contains(calls, "stop") {
		t.Errorf("dry-run must not change anything:\n%s", calls)
	}
}

func TestCleanupRunningRequiresYesWithoutTTY(t *testing.T) {
	fakeRuntime(t, "podman", fakeEngine)
	app, _, stderr := testApp(t, nil) // StdinTTY = false

	code := app.Run([]string{"cleanup", "--running"})
	if code != exitUsage {
		t.Errorf("exit = %d, want 2", code)
	}
	if !strings.Contains(stderr.String(), "--yes") {
		t.Errorf("stderr should point at --yes:\n%s", stderr.String())
	}
}

func TestCleanupRunningWithYes(t *testing.T) {
	log := fakeRuntime(t, "podman", fakeEngine)
	app, stdout, _ := testApp(t, nil)

	code := app.Run([]string{"cleanup", "--running", "--yes"})
	if code != exitOK {
		t.Fatalf("exit = %d", code)
	}
	calls := readLog(t, log)
	if !strings.Contains(calls, "stop def456") || !strings.Contains(calls, "rm def456") {
		t.Errorf("running container should be stopped then removed:\n%s", calls)
	}
	if !strings.Contains(calls, "rm abc123") {
		t.Errorf("stopped container should be removed:\n%s", calls)
	}
	if !strings.Contains(stdout.String(), "removed container def456") {
		t.Errorf("output should report removals:\n%s", stdout.String())
	}
}

func TestCleanupImages(t *testing.T) {
	log := fakeRuntime(t, "podman", fakeEngine)
	app, _, _ := testApp(t, nil)

	code := app.Run([]string{"cleanup", "--images", "--yes"})
	if code != exitOK {
		t.Fatalf("exit = %d", code)
	}
	calls := readLog(t, log)
	// both tools share docker.io/parrotsec/security: it must be handled once
	if strings.Count(calls, "rmi docker.io/parrotsec/security") != 1 {
		t.Errorf("shared image must be removed exactly once:\n%s", calls)
	}
	// containers are handled before images (§4.5)
	if strings.Index(calls, "rmi") < strings.Index(calls, "rm abc123") {
		t.Errorf("images must be removed after containers:\n%s", calls)
	}
}

func TestCleanupJSON(t *testing.T) {
	fakeRuntime(t, "podman", fakeEngine)
	app, stdout, _ := testApp(t, nil)

	code := app.Run([]string{"cleanup", "--dry-run", "--running", "--json"})
	if code != exitOK {
		t.Fatalf("exit = %d", code)
	}
	out := stdout.String()
	for _, want := range []string{`"dry_run": true`, `"containers_removed": [`, `"images_removed": [`} {
		if !strings.Contains(out, want) {
			t.Errorf("JSON missing %s:\n%s", want, out)
		}
	}
}

func TestCleanupInsideContainer(t *testing.T) {
	fakeRuntime(t, "podman", fakeEngine)
	app, _, _ := testApp(t, map[string]string{"container": "podman"})
	if code := app.Run([]string{"cleanup"}); code != exitRuntimeFail {
		t.Errorf("exit = %d, want 4 inside a container", code)
	}
}
