package utils

import (
	"testing"
)

// TestExtractIssuePrefixAllLetterHash tests issue #446:
// Base36 hashes can be all-letters (no digits), but isLikelyHash requires
// at least one digit to distinguish from English words.
// This causes all-letter hashes like "bat", "dev", "oil" to be rejected,
// falling back to first-hyphen extraction and giving wrong prefix.
//
// Hash length scales with birthday algorithm: 3, 4, 5, 6, 7, 8 chars.
// All lengths can be all-letters by chance.
//
// See: https://github.com/steveyegge/beads/issues/446
func TestExtractIssuePrefixAllLetterHash(t *testing.T) {
	// Only 3-char all-letter suffixes should be accepted as hashes.
	// 4+ char all-letter suffixes still require a digit.
	allLetterHashes := []struct {
		issueID  string
		expected string
	}{
		// 3-char all-letter suffixes (actual IDs from xa-adapt) - SHOULD WORK
		{"xa-adt-bat", "xa-adt"},
		{"xa-adt-dev", "xa-adt"},
		{"xa-adt-fbi", "xa-adt"},
		{"xa-adt-oil", "xa-adt"},

		// 3-char with digits - already works
		{"xa-adt-r71", "xa-adt"},
		{"xa-adt-b4r", "xa-adt"},
		{"xa-adt-0lj", "xa-adt"},
	}

	for _, tc := range allLetterHashes {
		t.Run(tc.issueID, func(t *testing.T) {
			result := ExtractIssuePrefix(tc.issueID)
			if result != tc.expected {
				t.Errorf("ExtractIssuePrefix(%q) = %q; want %q", tc.issueID, result, tc.expected)
			}
		})
	}
}

// TestExtractIssuePrefixWordSuffix tests word-like suffixes (bd-fasa regression)
// Word-like suffixes (4+ chars, no digits) use first-hyphen extraction because
// they're likely multi-part IDs where everything after first hyphen is the ID.
// This fixes bd-fasa regression where word-like suffixes were wrongly treated as hashes.
func TestExtractIssuePrefixWordSuffix(t *testing.T) {
	// Word-like suffixes (4+ chars, no digits) should use first-hyphen extraction
	// The entire part after first hyphen is the ID, not just the last segment
	wordSuffixes := []struct {
		issueID  string
		expected string
	}{
		{"vc-baseline-test", "vc"},  // bd-fasa: "baseline-test" is the ID, not "test"
		{"vc-baseline-hello", "vc"}, // bd-fasa: "baseline-hello" is the ID
		{"vc-some-feature", "vc"},   // bd-fasa: "some-feature" is the ID
	}

	for _, tc := range wordSuffixes {
		t.Run(tc.issueID, func(t *testing.T) {
			result := ExtractIssuePrefix(tc.issueID)
			if result != tc.expected {
				t.Errorf("ExtractIssuePrefix(%q) = %q; want %q", tc.issueID, result, tc.expected)
			}
		})
	}
}

// TestIsLikelyHashAllLetters verifies the root cause:
// isLikelyHash returns false for all-letter strings even though
// they are valid base36 hashes.
//
// Key insight: English word collision probability varies by length:
// - 3-char: 36^3 = 46K hashes, ~1000 common words = ~2% collision (TOO HIGH)
// - 4-char: 36^4 = 1.6M hashes, ~3000 common words = ~0.2% collision (acceptable)
// - 5+ char: collision rate negligible
//
// Proposed fix: accept all-letter for 3-char only, keep digit requirement for 4+.
func TestIsLikelyHashAllLetters(t *testing.T) {
	tests := []struct {
		suffix   string
		expected bool
		reason   string
	}{
		// With digits - should pass (and does)
		{"r71", true, "has digits"},
		{"b4r", true, "has digit"},
		{"0lj", true, "starts with digit"},
		{"a3f", true, "has digit"},
		{"a1b2", true, "4-char with digits"},
		{"test1", true, "5-char with digit"},

		// 3-char all letters - SHOULD pass (proposed fix)
		// English word collision is acceptable at 3 chars
		{"bat", true, "3-char base36 - accept all-letter"},
		{"dev", true, "3-char base36 - accept all-letter"},
		{"oil", true, "3-char base36 - accept all-letter"},
		{"fbi", true, "3-char base36 - accept all-letter"},
		{"abc", true, "3-char base36 - accept all-letter"},

		// 4+ char all letters - should FAIL (keep digit requirement)
		// Word collision is rare enough that digit requirement is safe
		{"test", false, "4-char all-letter - require digit"},
		{"abcd", false, "4-char all-letter - require digit"},
		{"hello", false, "5-char all-letter - require digit"},
		{"foobar", false, "6-char all-letter - require digit"},
		{"baseline", false, "8-char all-letter - require digit"},

		// Length bounds
		{"ab", false, "too short (2 chars)"},
		{"abcdefghi", false, "too long (9 chars)"},
	}

	for _, tc := range tests {
		t.Run(tc.suffix, func(t *testing.T) {
			result := isLikelyHash(tc.suffix)
			if result != tc.expected {
				t.Errorf("isLikelyHash(%q) = %v; want %v (%s)",
					tc.suffix, result, tc.expected, tc.reason)
			}
		})
	}
}

