package mailstore

import (
	"net"
	"testing"
)

// TestSpamScoreArithmetic exercises SpamScore's own weighting logic with synthetic
// dkimPass/spfPass inputs — CheckDNSBL still runs (it does live DNS), so this only
// asserts the score is monotonically at least as high when signals get worse, rather
// than pinning an exact network-dependent number.
func TestSpamScoreArithmetic(t *testing.T) {
	clean := SpamScore("203.0.113.1", map[string]string{"subject": "hello"}, true, true)
	noDKIM := SpamScore("203.0.113.1", map[string]string{"subject": "hello"}, false, true)
	noSPF := SpamScore("203.0.113.1", map[string]string{"subject": "hello"}, true, false)
	keyword := SpamScore("203.0.113.1", map[string]string{"subject": "WIN THE LOTTERY WINNER NOW"}, true, true)

	if noDKIM <= clean {
		t.Fatalf("missing DKIM should raise the score: clean=%d noDKIM=%d", clean, noDKIM)
	}
	if noSPF <= clean {
		t.Fatalf("failing SPF should raise the score: clean=%d noSPF=%d", clean, noSPF)
	}
	if keyword <= clean {
		t.Fatalf("a spam keyword in the subject should raise the score: clean=%d keyword=%d", clean, keyword)
	}
}

func TestEvalSPF(t *testing.T) {
	ip := net.ParseIP("203.0.113.10")
	other := net.ParseIP("198.51.100.5")

	tests := []struct {
		name   string
		record string
		ip     net.IP
		want   bool
	}{
		{"ip4 match passes", "v=spf1 ip4:203.0.113.0/24 -all", ip, true},
		{"ip4 no match hard fails", "v=spf1 ip4:203.0.113.0/24 -all", other, false},
		{"no all and no match is neutral", "v=spf1 ip4:203.0.113.0/24", other, true},
		{"soft fail all is neutral for unmatched ip", "v=spf1 ip4:203.0.113.0/24 ~all", other, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := evalSPF(tt.record, tt.ip, "example.com", 0)
			if got != tt.want {
				t.Fatalf("evalSPF(%q) = %v, want %v", tt.record, got, tt.want)
			}
		})
	}
}
