package models

import (
	"testing"
	"time"
)

// TestVocabulary tests the Vocabulary model
func TestVocabulary(t *testing.T) {
	t.Run("Create Vocabulary", func(t *testing.T) {
		vocab := &Vocabulary{
			ID:           "vocab-123",
			Word:         "hello",
			Level:        "beginner",
			Frequency:    100,
			IsActive:     true,
		}

		if vocab.Word != "hello" {
			t.Errorf("Expected word 'hello', got '%s'", vocab.Word)
		}

		if vocab.Level != "beginner" {
			t.Errorf("Expected level 'beginner', got '%s'", vocab.Level)
		}

		if vocab.Frequency != 100 {
			t.Errorf("Expected frequency 100, got %d", vocab.Frequency)
		}
	})

	t.Run("Vocabulary Validation", func(t *testing.T) {
		tests := []struct {
			name     string
			vocab    Vocabulary
			expected bool
		}{
			{
				name: "Valid Vocabulary",
				vocab: Vocabulary{
					ID:           "vocab-123",
					Word:         "test",
					Level:        "beginner",
					Frequency:    50,
				},
				expected: true,
			},
			{
				name: "Empty Word",
				vocab: Vocabulary{
					ID:           "vocab-123",
					Word:         "",
					Level:        "beginner",
				},
				expected: false,
			},
			{
				name: "Invalid Level",
				vocab: Vocabulary{
					ID:           "vocab-123",
					Word:         "test",
					Level:        "invalid",
				},
				expected: false,
			},
			{
				name: "Negative Frequency",
				vocab: Vocabulary{
					ID:           "vocab-123",
					Word:         "test",
					Level:        "beginner",
					Frequency:    -1,
				},
				expected: false,
			},
		}

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

// validateVocabulary is a helper function for testing vocabulary validation
func validateVocabulary(vocab Vocabulary) bool {
	if vocab.Word == "" {
		return false
	}
	validLevels := []string{"beginner", "intermediate", "advanced"}
	validLevel := false
	for _, level := range validLevels {
		if vocab.Level == level {
			validLevel = true
			break
		}
	}
	if !validLevel {
		return false
	}
	if vocab.Frequency < 0 {
		return false
	}
	return true
}

// TestVocabularyCategory tests the VocabularyCategory model
func TestVocabularyCategory(t *testing.T) {
	t.Run("Create VocabularyCategory", func(t *testing.T) {
		category := &VocabularyCategory{
			ID:          "cat-123",
			Name:        "Animals",
			Level:       "beginner",
			SortOrder:   1,
			IsActive:    true,
		}

		if category.Name != "Animals" {
			t.Errorf("Expected name 'Animals', got '%s'", category.Name)
		}

		if category.Level != "beginner" {
			t.Errorf("Expected level 'beginner', got '%s'", category.Level)
		}

		if category.SortOrder != 1 {
			t.Errorf("Expected sort order 1, got %d", category.SortOrder)
		}
	})

	t.Run("Category Validation", func(t *testing.T) {
		tests := []struct {
			name     string
			category VocabularyCategory
			expected bool
		}{
			{
				name: "Valid Category",
				category: VocabularyCategory{
					ID:          "cat-123",
					Name:        "Animals",
					Level:       "beginner",
					SortOrder:   1,
				},
				expected: true,
			},
			{
				name: "Empty Name",
				category: VocabularyCategory{
					ID:          "cat-123",
					Name:        "",
					Level:       "beginner",
				},
				expected: false,
			},
			{
				name: "Invalid Level",
				category: VocabularyCategory{
					ID:          "cat-123",
					Name:        "Animals",
					Level:       "invalid",
				},
				expected: false,
			},
		}

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

// validateVocabularyCategory is a helper function for testing vocabulary category validation
func validateVocabularyCategory(category VocabularyCategory) bool {
	if category.Name == "" {
		return false
	}
	validLevels := []string{"beginner", "intermediate", "advanced"}
	validLevel := false
	for _, level := range validLevels {
		if category.Level == level {
			validLevel = true
			break
		}
	}
	return validLevel
}

// TestVocabularyDefinition tests the VocabularyDefinition model
func TestVocabularyDefinition(t *testing.T) {
	t.Run("Create VocabularyDefinition", func(t *testing.T) {
		definition := &VocabularyDefinition{
			ID:           "def-123",
			VocabularyID: "vocab-123",
			PartOfSpeech: "noun",
			Definition:   "A greeting or expression of goodwill",
			SortOrder:    1,
		}

		if definition.PartOfSpeech != "noun" {
			t.Errorf("Expected part of speech 'noun', got '%s'", definition.PartOfSpeech)
		}

		if definition.Definition != "A greeting or expression of goodwill" {
			t.Errorf("Expected definition 'A greeting or expression of goodwill', got '%s'", definition.Definition)
		}
	})

	t.Run("Definition Validation", func(t *testing.T) {
		tests := []struct {
			name       string
			definition VocabularyDefinition
			expected   bool
		}{
			{
				name: "Valid Definition",
				definition: VocabularyDefinition{
					ID:           "def-123",
					VocabularyID: "vocab-123",
					PartOfSpeech: "noun",
					Definition:   "A greeting",
				},
				expected: true,
			},
			{
				name: "Empty VocabularyID",
				definition: VocabularyDefinition{
					ID:           "def-123",
					VocabularyID: "",
					PartOfSpeech: "noun",
					Definition:   "A greeting",
				},
				expected: false,
			},
			{
				name: "Empty Definition",
				definition: VocabularyDefinition{
					ID:           "def-123",
					VocabularyID: "vocab-123",
					PartOfSpeech: "noun",
					Definition:   "",
				},
				expected: false,
			},
		}

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

// validateVocabularyDefinition is a helper function for testing vocabulary definition validation
func validateVocabularyDefinition(definition VocabularyDefinition) bool {
	if definition.VocabularyID == "" {
		return false
	}
	if definition.Definition == "" {
		return false
	}
	return true
}

// TestUserVocabularyProgress tests the UserVocabularyProgress model
func TestUserVocabularyProgress(t *testing.T) {
	t.Run("Create UserVocabularyProgress", func(t *testing.T) {
		now := time.Now()
		progress := &UserVocabularyProgress{
			UserID:            1,
			VocabularyID:      "vocab-123",
			MasteryLevel:      75,
			StudyCount:        10,
			CorrectCount:      8,
			IncorrectCount:    2,
			LastStudiedAt:     &now,
			IsMarkedDifficult: false,
			IsFavorite:        true,
		}

		if progress.UserID != 1 {
			t.Errorf("Expected UserID 1, got %d", progress.UserID)
		}

		if progress.MasteryLevel != 75 {
			t.Errorf("Expected MasteryLevel 75, got %d", progress.MasteryLevel)
		}

		if progress.StudyCount != 10 {
			t.Errorf("Expected StudyCount 10, got %d", progress.StudyCount)
		}
	})

	t.Run("Progress Validation", func(t *testing.T) {
		tests := []struct {
			name     string
			progress UserVocabularyProgress
			expected bool
		}{
			{
				name: "Valid Progress",
				progress: UserVocabularyProgress{
					UserID:       1,
					VocabularyID: "vocab-123",
					MasteryLevel: 75,
					StudyCount:   10,
				},
				expected: true,
			},
			{
				name: "Invalid UserID",
				progress: UserVocabularyProgress{
					UserID:       0,
					VocabularyID: "vocab-123",
					MasteryLevel: 75,
				},
				expected: false,
			},
			{
				name: "Invalid MasteryLevel",
				progress: UserVocabularyProgress{
					UserID:       1,
					VocabularyID: "vocab-123",
					MasteryLevel: 150, // Over 100
				},
				expected: false,
			},
			{
				name: "Empty VocabularyID",
				progress: UserVocabularyProgress{
					UserID:       1,
					VocabularyID: "",
					MasteryLevel: 75,
				},
				expected: false,
			},
		}

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

// validateUserVocabularyProgress is a helper function for testing user vocabulary progress validation
func validateUserVocabularyProgress(progress UserVocabularyProgress) bool {
	if progress.UserID <= 0 {
		return false
	}
	if progress.VocabularyID == "" {
		return false
	}
	if progress.MasteryLevel < 0 || progress.MasteryLevel > 100 {
		return false
	}
	return true
}

// TestVocabularyTest tests the VocabularyTest model
func TestVocabularyTest(t *testing.T) {
	t.Run("Create VocabularyTest", func(t *testing.T) {
		test := &VocabularyTest{
			UserID:       1,
			TestType:     "placement",
			Level:        "beginner",
			TotalWords:   20,
			CorrectWords: 15,
			Score:        75.0,
			Duration:     300, // 5 minutes
			StartedAt:    time.Now(),
		}

		if test.UserID != 1 {
			t.Errorf("Expected UserID 1, got %d", test.UserID)
		}

		if test.TestType != "placement" {
			t.Errorf("Expected TestType 'placement', got '%s'", test.TestType)
		}

		if test.Score != 75.0 {
			t.Errorf("Expected Score 75.0, got %f", test.Score)
		}
	})

	t.Run("Test Validation", func(t *testing.T) {
		tests := []struct {
			name     string
			test     VocabularyTest
			expected bool
		}{
			{
				name: "Valid Test",
				test: VocabularyTest{
					UserID:       1,
					TestType:     "placement",
					Level:        "beginner",
					TotalWords:   20,
					CorrectWords: 15,
				},
				expected: true,
			},
			{
				name: "Invalid UserID",
				test: VocabularyTest{
					UserID:       0,
					TestType:     "placement",
					TotalWords:   20,
				},
				expected: false,
			},
			{
				name: "Invalid TestType",
				test: VocabularyTest{
					UserID:       1,
					TestType:     "invalid",
					TotalWords:   20,
				},
				expected: false,
			},
			{
				name: "Correct Words Greater Than Total",
				test: VocabularyTest{
					UserID:       1,
					TestType:     "placement",
					TotalWords:   20,
					CorrectWords: 25,
				},
				expected: false,
			},
		}

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

// validateVocabularyTest is a helper function for testing vocabulary test validation
func validateVocabularyTest(test VocabularyTest) bool {
	if test.UserID <= 0 {
		return false
	}
	validTestTypes := []string{"placement", "progress", "review"}
	validTestType := false
	for _, testType := range validTestTypes {
		if test.TestType == testType {
			validTestType = true
			break
		}
	}
	if !validTestType {
		return false
	}
	if test.CorrectWords > test.TotalWords {
		return false
	}
	return true
}