package updater

import (
	"strings"
	"testing"
)

func TestParseSHA256SumsGNUFormat(t *testing.T) {
	body := []byte(`# header comment
0000000000000000000000000000000000000000000000000000000000000001  banger-v0.1.0-linux-amd64.tar.gz
0000000000000000000000000000000000000000000000000000000000000002  banger-v0.1.0-linux-amd64.tar.gz.sig
`)
	got, err := ParseSHA256Sums(body)
	if err != nil {
		t.Fatalf("ParseSHA256Sums: %v", err)
	}
	if got["banger-v0.1.0-linux-amd64.tar.gz"] != "0000000000000000000000000000000000000000000000000000000000000001" {
		t.Fatalf("tarball digest = %q", got["banger-v0.1.0-linux-amd64.tar.gz"])
	}
	if len(got) != 2 {
		t.Fatalf("got %d entries, want 2", len(got))
	}
}

func TestParseSHA256SumsBSDFormat(t *testing.T) {
	body := []byte(`SHA256 (banger-v0.1.0-linux-amd64.tar.gz) = 0000000000000000000000000000000000000000000000000000000000000001
`)
	got, err := ParseSHA256Sums(body)
	if err != nil {
		t.Fatalf("ParseSHA256Sums: %v", err)
	}
	if got["banger-v0.1.0-linux-amd64.tar.gz"] != "0000000000000000000000000000000000000000000000000000000000000001" {
		t.Fatalf("digest = %q", got["banger-v0.1.0-linux-amd64.tar.gz"])
	}
}

func TestParseSHA256SumsBinaryStarPrefix(t *testing.T) {
	// `sha256sum -b` emits `<digest>  *<filename>`.
	body := []byte(`0000000000000000000000000000000000000000000000000000000000000001 *banger-v0.1.0-linux-amd64.tar.gz
`)
	got, err := ParseSHA256Sums(body)
	if err != nil {
		t.Fatalf("ParseSHA256Sums: %v", err)
	}
	if _, ok := got["banger-v0.1.0-linux-amd64.tar.gz"]; !ok {
		t.Fatalf("entries = %v, want star-prefix stripped", got)
	}
}

func TestParseSHA256SumsTolerantOfBlankAndComments(t *testing.T) {
	body := []byte(`
# top comment
0000000000000000000000000000000000000000000000000000000000000001  a

# inline comment
0000000000000000000000000000000000000000000000000000000000000002  b
`)
	got, err := ParseSHA256Sums(body)
	if err != nil {
		t.Fatalf("ParseSHA256Sums: %v", err)
	}
	if len(got) != 2 {
		t.Fatalf("got %d, want 2", len(got))
	}
}

func TestParseSHA256SumsRejectsMalformed(t *testing.T) {
	for _, tc := range []struct {
		name string
		body string
	}{
		{name: "short_digest", body: "abc  file"},
		{name: "non_hex_digest", body: "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz  file"},
		{name: "no_filename", body: "0000000000000000000000000000000000000000000000000000000000000001"},
		{name: "empty_body", body: ""},
		{name: "only_comments", body: "# comment\n# more\n"},
		{name: "bsd_no_eq", body: "SHA256 (file) 0000000000000000000000000000000000000000000000000000000000000001"},
	} {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			if _, err := ParseSHA256Sums([]byte(tc.body)); err == nil {
				t.Fatalf("expected error for %s", tc.name)
			}
		})
	}
}

func TestParseSHA256SumsLowercasesDigest(t *testing.T) {
	body := []byte(`ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890  upper
`)
	got, err := ParseSHA256Sums(body)
	if err != nil {
		t.Fatalf("ParseSHA256Sums: %v", err)
	}
	if got["upper"] != strings.ToLower("ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890") {
		t.Fatalf("digest not lowercased: %q", got["upper"])
	}
}
