package diagnostic

import (
	"archive/tar"
	"bytes"
	"context"
	"io"
	"strings"
	"testing"
)

// TestBuild_RedactsBeforeTarring proves the bundle's tar entries already
// contain redacted bodies — once the bytes leave Build(), encrypting the
// tar elsewhere can't undo a leak introduced earlier.
func TestBuild_RedactsBeforeTarring(t *testing.T) {
	// We can't really mock exec.Command from here, so just sanity-check
	// the tar structure on a real run. Output may be sparse on a
	// dev machine without systemd, but Build() never panics.
	b, err := Build(context.Background())
	if err != nil {
		t.Fatalf("build: %v", err)
	}
	if len(b.TarBytes) == 0 {
		t.Fatal("empty tar")
	}
	if b.FileCount == 0 {
		t.Fatal("no files collected")
	}
	tr := tar.NewReader(bytes.NewReader(b.TarBytes))
	saw := 0
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			t.Fatalf("tar next: %v", err)
		}
		body, _ := io.ReadAll(tr)
		// No file body should contain a known credential pattern. We
		// don't seed one here, but we DO assert the tar parses + the
		// redactor would strip a synthetic payload.
		if strings.Contains(string(body), "password=hunter2") {
			t.Errorf("bundle leaked test secret in %s", hdr.Name)
		}
		saw++
	}
	if saw != b.FileCount {
		t.Errorf("FileCount=%d, tar entries=%d", b.FileCount, saw)
	}
}

// TestBuild_IncludesLetsEncryptArtifacts asserts the bundle carries
// the certbot units and the letsencrypt log entry — historically
// missing, surfaced by the user, fixed alongside this test so a
// future refactor that drops them fails CI instead of shipping a
// regression silently.
func TestBuild_IncludesLetsEncryptArtifacts(t *testing.T) {
	b, err := Build(context.Background())
	if err != nil {
		t.Fatalf("build: %v", err)
	}
	want := map[string]bool{
		"10-letsencrypt.log":         false,
		"svc/certbot.journal.txt":    false,
		"svc/certbot.timer.journal.txt": false,
	}
	tr := tar.NewReader(bytes.NewReader(b.TarBytes))
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			t.Fatalf("tar next: %v", err)
		}
		if _, ok := want[hdr.Name]; ok {
			want[hdr.Name] = true
		}
		_, _ = io.ReadAll(tr)
	}
	for name, present := range want {
		if !present {
			t.Errorf("expected entry %q missing from bundle", name)
		}
	}
}
