package email

import (
	"net/mail"
	"strings"
	"testing"
)

func headers(t *testing.T, raw string) mail.Header {
	t.Helper()
	m, err := mail.ReadMessage(strings.NewReader(strings.ReplaceAll(raw, "\n", "\r\n") + "\r\n\r\nbody\r\n"))
	if err != nil {
		t.Fatalf("read headers: %v", err)
	}
	return m.Header
}

func TestClassifyJunk(t *testing.T) {
	cases := []struct {
		name   string
		raw    string
		junk   bool
		reason string
	}{
		{"personal", "From: a@b.c\nSubject: привет", false, ""},
		{"list-unsubscribe", "From: a@b.c\nList-Unsubscribe: <mailto:u@b.c>", true, "list-unsubscribe"},
		{"list-id", "From: a@b.c\nList-Id: <golang-nuts.example>", true, "list-id"},
		{"precedence bulk", "From: a@b.c\nPrecedence: bulk", true, "precedence"},
		{"auto-submitted", "From: a@b.c\nAuto-Submitted: auto-generated", true, "auto-submitted"},
		{"auto-submitted no", "From: a@b.c\nAuto-Submitted: no", false, ""},
		{"spam flag", "From: a@b.c\nX-Spam-Flag: YES", true, "x-spam-flag"},
		{"spam status", "From: a@b.c\nX-Spam-Status: Yes, score=9.1", true, "x-spam-status"},
		{"spam status no", "From: a@b.c\nX-Spam-Status: No, score=0.1", false, ""},
		// X-GM-LABELS is a Gmail FETCH data item, not a header, so it never
		// reaches classifyJunk through this client. The rule that matched it was
		// removed rather than left claiming a Promotions filter that never ran.
		{"gmail label header is not a rule", "From: a@b.c\nX-Gmail-Labels: Inbox,CATEGORY_PROMOTIONS", false, ""},
	}
	for _, c := range cases {
		t.Run(c.name, func(t *testing.T) {
			junk, reason := classifyJunk(headers(t, c.raw))
			if junk != c.junk || reason != c.reason {
				t.Errorf("classifyJunk = (%v, %q), want (%v, %q)", junk, reason, c.junk, c.reason)
			}
		})
	}
}

func TestNewsletterFixtureIsJunk(t *testing.T) {
	msg, err := ParseMessage(9, fixture(t, "newsletter.eml"))
	if err != nil {
		t.Fatalf("parse: %v", err)
	}
	if !msg.Junk {
		t.Fatal("a newsletter with List-Unsubscribe + Precedence: bulk must be junk")
	}
	// The reason is what gets logged, so it must never carry mail content.
	if strings.Contains(msg.JunkReason, "@") || strings.Contains(msg.JunkReason, "Скидки") {
		t.Errorf("junk reason leaks content: %q", msg.JunkReason)
	}
}
