package cli

import (
	"context"
	"strings"
	"testing"

	"tsne.dev/hopper/internal/bunny"
)

// TestDryRunPushStubsUploads asserts that under dry-run the push flow performs
// NO uploads against the wrapped API, yet prints the normal per-file action
// line and summary (logging is owned by the command, not the decorator). The
// recording fake is the wrapped (real-stand-in) API, so a zero put-count
// provably shows the write side was never invoked.
func TestDryRunPushStubsUploads(t *testing.T) {
	arc := makeArchive(t, []tarEntry{
		{name: "index.html", body: "<html>"},
		{name: "assets/app.abc.js", body: "console.log(1)"},
	})

	spy := newFakeAPI()
	out, _ := captureLogs(t)
	dryRun = true

	if err := runPush(arc, dryRunStorageAPI{spy}); err != nil {
		t.Fatalf("push: %v", err)
	}

	if got := spy.paths(); len(got) != 0 {
		t.Fatalf("expected no real uploads, got %v", got)
	}

	s := out.String()
	for _, want := range []string{
		"[dryrun] uploading index.html",
		"[dryrun] uploading assets/app.abc.js",
		"uploaded: 2",
	} {
		if !strings.Contains(s, want) {
			t.Fatalf("output missing %q; got:\n%s", want, s)
		}
	}
}

// TestDryRunDeleteStubbed asserts Delete never reaches the wrapped API
// (reused by prune in issue 008, which will own the delete log line).
func TestDryRunDeleteStubbed(t *testing.T) {
	spy := newFakeAPI()
	api := dryRunStorageAPI{spy}

	if err := api.Delete(context.Background(), "old/file.js"); err != nil {
		t.Fatalf("Delete: %v", err)
	}
	if len(spy.deletes) != 0 {
		t.Fatalf("expected no real deletes, got %v", spy.deletes)
	}
}

// TestDryRunListDelegates asserts the read side still reaches the wrapped API
// (real Bunny in production), unaffected by the write stubbing.
func TestDryRunListDelegates(t *testing.T) {
	spy := newFakeAPI()
	spy.lists[""] = []bunny.Object{{Path: "a.js", Size: 3}}
	api := dryRunStorageAPI{spy}

	it := api.List(context.Background(), "")
	var got []bunny.Object
	for it.Next() {
		got = append(got, it.Object())
	}
	if err := it.Err(); err != nil {
		t.Fatalf("List: %v", err)
	}
	if len(got) != 1 || got[0].Path != "a.js" {
		t.Fatalf("List delegate = %v", got)
	}
}
