package publications

import (
	"testing"

	"github.com/breakpilot/edu-search-service/internal/database"
)

func TestContainsPub_ByDOI(t *testing.T) {
	doi1 := "10.1000/test1"
	doi2 := "10.1000/test2"
	doi3 := "10.1000/test3"

	pubs := []*database.Publication{
		{Title: "Paper 1", DOI: &doi1},
		{Title: "Paper 2", DOI: &doi2},
	}

	tests := []struct {
		name     string
		pub      *database.Publication
		expected bool
	}{
		{
			name:     "DOI exists in list",
			pub:      &database.Publication{Title: "Different Title", DOI: &doi1},
			expected: true,
		},
		{
			name:     "DOI does not exist",
			pub:      &database.Publication{Title: "New Paper", DOI: &doi3},
			expected: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := containsPub(pubs, tt.pub)
			if result != tt.expected {
				t.Errorf("Expected %v, got %v", tt.expected, result)
			}
		})
	}
}

func TestContainsPub_ByTitle(t *testing.T) {
	pubs := []*database.Publication{
		{Title: "Machine Learning Applications"},
		{Title: "Deep Neural Networks"},
	}

	tests := []struct {
		name     string
		pub      *database.Publication
		expected bool
	}{
		{
			name:     "Title exists in list",
			pub:      &database.Publication{Title: "Machine Learning Applications"},
			expected: true,
		},
		{
			name:     "Title does not exist",
			pub:      &database.Publication{Title: "New Research Paper"},
			expected: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := containsPub(pubs, tt.pub)
			if result != tt.expected {
				t.Errorf("Expected %v, got %v", tt.expected, result)
			}
		})
	}
}

func TestContainsIgnoreCase(t *testing.T) {
	tests := []struct {
		name     string
		s        string
		substr   string
		expected bool
	}{
		{"Exact match", "Hello World", "Hello", true},
		{"Case insensitive", "Hello World", "hello", true},
		{"Case insensitive uppercase", "HELLO WORLD", "world", true},
		{"Substring in middle", "The quick brown fox", "brown", true},
		{"No match", "Hello World", "xyz", false},
		{"Empty substring", "Hello", "", true},
		{"Empty string", "", "test", false},
		{"Both empty", "", "", true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := containsIgnoreCase(tt.s, tt.substr)
			if result != tt.expected {
				t.Errorf("containsIgnoreCase(%q, %q) = %v, expected %v",
					tt.s, tt.substr, result, tt.expected)
			}
		})
	}
}

func TestEqualFold(t *testing.T) {
	tests := []struct {
		name     string
		s1       string
		s2       string
		expected bool
	}{
		{"Same string", "hello", "hello", true},
		{"Different case", "Hello", "hello", true},
		{"All uppercase", "HELLO", "hello", true},
		{"Mixed case", "HeLLo", "hEllO", true},
		{"Different strings", "hello", "world", false},
		{"Different length", "hello", "hi", false},
		{"Empty strings", "", "", true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := equalFold(tt.s1, tt.s2)
			if result != tt.expected {
				t.Errorf("equalFold(%q, %q) = %v, expected %v",
					tt.s1, tt.s2, result, tt.expected)
			}
		})
	}
}

func TestFindAuthorPosition(t *testing.T) {
	pub := &database.Publication{
		Title: "Test Paper",
		Authors: []string{
			"John Smith",
			"Maria Müller",
			"Hans Weber",
		},
	}

	tests := []struct {
		name     string
		staff    *database.UniversityStaff
		expected int
	}{
		{
			name: "First author",
			staff: &database.UniversityStaff{
				LastName: "Smith",
			},
			expected: 1,
		},
		{
			name: "Second author",
			staff: &database.UniversityStaff{
				LastName: "Müller",
			},
			expected: 2,
		},
		{
			name: "Third author",
			staff: &database.UniversityStaff{
				LastName: "Weber",
			},
			expected: 3,
		},
		{
			name: "Author not found",
			staff: &database.UniversityStaff{
				LastName: "Unknown",
			},
			expected: 0,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := findAuthorPosition(pub, tt.staff)
			if result != tt.expected {
				t.Errorf("Expected position %d, got %d for author %s",
					tt.expected, result, tt.staff.LastName)
			}
		})
	}
}
