package web

import "testing"

func TestPreviewText(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name string
		in   string
		max  int
		want string
	}{
		{
			name: "empty input",
			in:   "",
			max:  160,
			want: "",
		},
		{
			name: "whitespace-only input",
			in:   "   \n\t  ",
			max:  160,
			want: "",
		},
		{
			name: "short string unchanged",
			in:   "A tidy little summary",
			max:  160,
			want: "A tidy little summary",
		},
		{
			name: "short single sentence unchanged",
			in:   "Hello there.",
			max:  160,
			want: "Hello there.",
		},
		{
			name: "first sentence taken when more follows",
			in:   "First sentence. Second sentence that we drop.",
			max:  160,
			want: "First sentence.",
		},
		{
			name: "first sentence with question mark",
			in:   "What is this? It is a preview.",
			max:  160,
			want: "What is this?",
		},
		{
			name: "long string truncated on word boundary with ellipsis",
			// 5 ten-char words past the limit; max cuts mid "ones".
			in:  "alpha bravo charlie delta echo foxtrot golf hotel india juliet",
			max: 30,
			// runes[:30] = "alpha bravo charlie delta echo"; ends exactly on a
			// word so the next char would be a space — backs off to last space.
			want: "alpha bravo charlie delta…",
		},
		{
			name: "no mid-word cut",
			in:   "internationalization frameworks everywhere today",
			max:  25,
			// runes[:25] = "internationalization fram" — back off to the space
			// after the first word; never emit a partial word.
			want: "internationalization…",
		},
		{
			name: "multibyte safe truncation",
			// Accented + emoji runes; cutting on rune indices must not split a
			// multibyte sequence.
			in:   "café déjà vû señor naïve résumé piñata fiancé",
			max:  20,
			want: "café déjà vû señor…",
		},
		{
			name: "multibyte short unchanged",
			in:   "café señor",
			max:  160,
			want: "café señor",
		},
		{
			name: "collapses internal whitespace",
			in:   "line one\n\n   line two\tline three",
			max:  160,
			want: "line one line two line three",
		},
		{
			name: "sentence beyond max falls back to char truncation",
			in:   "alpha bravo charlie delta echo foxtrot golf. short.",
			max:  20,
			want: "alpha bravo charlie…",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			got := previewText(tt.in, tt.max)
			if got != tt.want {
				t.Errorf("previewText(%q, %d) = %q, want %q", tt.in, tt.max, got, tt.want)
			}
		})
	}
}
