package staff

import (
	"testing"

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

func TestParseName_FullName_WithTitle(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name           string
		fullName       string
		expectedFirst  string
		expectedLast   string
		expectedTitle  bool
	}{
		{
			name:           "Prof. Dr. with first and last name",
			fullName:       "Prof. Dr. Hans Müller",
			expectedFirst:  "Hans",
			expectedLast:   "Müller",
			expectedTitle:  true,
		},
		{
			name:           "Dr. with first and last name",
			fullName:       "Dr. Maria Schmidt",
			expectedFirst:  "Maria",
			expectedLast:   "Schmidt",
			expectedTitle:  true,
		},
		{
			name:           "Simple name without title",
			fullName:       "Thomas Weber",
			expectedFirst:  "Thomas",
			expectedLast:   "Weber",
			expectedTitle:  false,
		},
		{
			name:           "Multiple first names",
			fullName:       "Prof. Dr. Hans-Peter Meier",
			expectedFirst:  "Hans-Peter",
			expectedLast:   "Meier",
			expectedTitle:  true,
		},
		{
			name:           "Single name",
			fullName:       "Müller",
			expectedFirst:  "",
			expectedLast:   "Müller",
			expectedTitle:  false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			person := &database.UniversityStaff{}
			crawler.parseName(tt.fullName, person)

			firstName := ""
			if person.FirstName != nil {
				firstName = *person.FirstName
			}

			if firstName != tt.expectedFirst {
				t.Errorf("First name: expected %q, got %q", tt.expectedFirst, firstName)
			}
			if person.LastName != tt.expectedLast {
				t.Errorf("Last name: expected %q, got %q", tt.expectedLast, person.LastName)
			}
			hasTitle := person.Title != nil && *person.Title != ""
			if hasTitle != tt.expectedTitle {
				t.Errorf("Has title: expected %v, got %v", tt.expectedTitle, hasTitle)
			}
		})
	}
}

func TestClassifyPosition_Professor(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
		expected string
	}{
		{"Full Professor", "Professor für Informatik", "professor"},
		{"Prof abbreviation", "Prof. Dr. Müller", "professor"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.classifyPosition(tt.position)
			if result == nil {
				t.Errorf("Expected %q, got nil for position %q", tt.expected, tt.position)
				return
			}
			if *result != tt.expected {
				t.Errorf("Expected %q, got %q for position %q", tt.expected, *result, tt.position)
			}
		})
	}
}

func TestClassifyPosition_Postdoc(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
		expected string
	}{
		{"Postdoc", "Postdoc in Machine Learning", "postdoc"},
		{"Post-Doc hyphenated", "Post-Doc", "postdoc"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.classifyPosition(tt.position)
			if result == nil {
				t.Errorf("Expected %q, got nil for position %q", tt.expected, tt.position)
				return
			}
			if *result != tt.expected {
				t.Errorf("Expected %q, got %q for position %q", tt.expected, *result, tt.position)
			}
		})
	}
}

func TestClassifyPosition_PhDStudent(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
		expected string
	}{
		{"Doktorand", "Doktorand", "phd_student"},
		{"PhD Student", "PhD Student", "phd_student"},
		{"Promovend", "Promovend", "phd_student"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.classifyPosition(tt.position)
			if result == nil {
				t.Errorf("Expected %q, got nil for position %q", tt.expected, tt.position)
				return
			}
			if *result != tt.expected {
				t.Errorf("Expected %q, got %q for position %q", tt.expected, *result, tt.position)
			}
		})
	}
}

func TestClassifyPosition_Admin(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
		expected string
	}{
		{"Sekretariat", "Sekretärin", "admin"},
		{"Verwaltung", "Verwaltung", "admin"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.classifyPosition(tt.position)
			if result == nil {
				t.Errorf("Expected %q, got nil for position %q", tt.expected, tt.position)
				return
			}
			if *result != tt.expected {
				t.Errorf("Expected %q, got %q for position %q", tt.expected, *result, tt.position)
			}
		})
	}
}

func TestClassifyPosition_Researcher(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
		expected string
	}{
		{"Wissenschaftlicher Mitarbeiter", "Wissenschaftlicher Mitarbeiter", "researcher"},
		{"Researcher", "Senior Researcher", "researcher"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.classifyPosition(tt.position)
			if result == nil {
				t.Errorf("Expected %q, got nil for position %q", tt.expected, tt.position)
				return
			}
			if *result != tt.expected {
				t.Errorf("Expected %q, got %q for position %q", tt.expected, *result, tt.position)
			}
		})
	}
}

func TestClassifyPosition_Student(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
		expected string
	}{
		{"Studentische Hilfskraft", "Studentische Hilfskraft", "student"},
		{"HiWi", "Student (HiWi)", "student"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.classifyPosition(tt.position)
			if result == nil {
				t.Errorf("Expected %q, got nil for position %q", tt.expected, tt.position)
				return
			}
			if *result != tt.expected {
				t.Errorf("Expected %q, got %q for position %q", tt.expected, *result, tt.position)
			}
		})
	}
}

func TestIsProfessor_True(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
	}{
		{"Professor keyword", "Professor für Mathematik"},
		{"Prof. abbreviation", "Prof. Dr. Müller"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.isProfessor(tt.position)
			if !result {
				t.Errorf("Expected true for position=%q", tt.position)
			}
		})
	}
}

func TestIsProfessor_False(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name     string
		position string
	}{
		{"Dr. only", "Dr. Wissenschaftlicher Mitarbeiter"},
		{"Doktorand", "Doktorand"},
		{"Technical staff", "Laboringenieur"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.isProfessor(tt.position)
			if result {
				t.Errorf("Expected false for position=%q", tt.position)
			}
		})
	}
}

func TestLooksLikePosition_True(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name string
		text string
	}{
		{"Professor", "Professor für Informatik"},
		{"Wissenschaftlicher Mitarbeiter", "Wissenschaftlicher Mitarbeiter"},
		{"Doktorand", "Doktorand"},
		{"Sekretär", "Sekretärin"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.looksLikePosition(tt.text)
			if !result {
				t.Errorf("Expected true for text=%q", tt.text)
			}
		})
	}
}

func TestLooksLikePosition_False(t *testing.T) {
	crawler := &StaffCrawler{}

	tests := []struct {
		name string
		text string
	}{
		{"Name", "Hans Müller"},
		{"Email", "test@example.com"},
		{"Random text", "Room 123"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := crawler.looksLikePosition(tt.text)
			if result {
				t.Errorf("Expected false for text=%q", tt.text)
			}
		})
	}
}

func TestResolveURL(t *testing.T) {
	tests := []struct {
		name     string
		baseURL  string
		href     string
		expected string
	}{
		{"Absolute URL", "https://example.com", "https://other.com/page", "https://other.com/page"},
		{"Relative path", "https://example.com/team", "/person/123", "https://example.com/person/123"},
		{"Relative no slash", "https://example.com/team/", "member", "https://example.com/team/member"},
		{"Empty href", "https://example.com", "", ""},
		{"Root relative", "https://example.com/a/b/c", "/root", "https://example.com/root"},
	}

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