package projects

import (
	"testing"
)

func TestClassificationOutputParsing(t *testing.T) {
	// Test data representing expected LLM classification responses
	tests := []struct {
		name     string
		input    classificationOutput
		expected map[int]string
	}{
		{
			name: "real projects from cyberia-to",
			input: classificationOutput{
				Classifications: []projectClassification{
					{Number: 2, Category: "task", Reasoning: "Rockets is a development project for tracking features"},
					{Number: 3, Category: "supply", Reasoning: "Supply management for inventory tracking"},
					{Number: 33, Category: "infrastructure", Reasoning: "DevOps Force handles infrastructure"},
				},
			},
			expected: map[int]string{
				2:  "task",
				3:  "supply",
				33: "infrastructure",
			},
		},
		{
			name: "mixed categories",
			input: classificationOutput{
				Classifications: []projectClassification{
					{Number: 1, Category: "operations", Reasoning: "Business operations board"},
					{Number: 2, Category: "other", Reasoning: "Unclear purpose"},
				},
			},
			expected: map[int]string{
				1: "operations",
				2: "other",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Create projects to apply classifications to
			projects := make([]Project, 0, len(tt.input.Classifications))
			projectMap := make(map[int]*Project)

			for _, c := range tt.input.Classifications {
				p := Project{Number: c.Number, Title: "Test Project"}
				projects = append(projects, p)
				projectMap[c.Number] = &projects[len(projects)-1]
			}

			// Apply classifications (simulating what classifyProjects does)
			for _, classification := range tt.input.Classifications {
				if proj, exists := projectMap[classification.Number]; exists {
					proj.Category = classification.Category
					proj.CategoryReasoning = classification.Reasoning
				}
			}

			// Verify
			for _, proj := range projects {
				expectedCategory := tt.expected[proj.Number]
				if proj.Category != expectedCategory {
					t.Errorf("project #%d: expected category %q, got %q",
						proj.Number, expectedCategory, proj.Category)
				}
				if proj.CategoryReasoning == "" {
					t.Errorf("project #%d: expected non-empty reasoning", proj.Number)
				}
			}
		})
	}
}

func TestClassificationInputPreparation(t *testing.T) {
	tests := []struct {
		name           string
		projects       []Project
		expectedCount  int
		expectedClosed int
	}{
		{
			name: "filters closed projects",
			projects: []Project{
				{Number: 1, Title: "Open Project", Closed: false},
				{Number: 2, Title: "Closed Project", Closed: true},
				{Number: 3, Title: "Another Open", Closed: false},
			},
			expectedCount:  2,
			expectedClosed: 1,
		},
		{
			name: "filters already classified",
			projects: []Project{
				{Number: 1, Title: "Unclassified", Category: ""},
				{Number: 2, Title: "Already Classified", Category: "task"},
			},
			expectedCount:  1,
			expectedClosed: 0,
		},
		{
			name:          "empty input",
			projects:      []Project{},
			expectedCount: 0,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Prepare input like classifyProjects does
			input := classificationInput{
				Projects: make([]projectInfo, 0),
			}

			for _, proj := range tt.projects {
				if proj.Category == "" && !proj.Closed {
					input.Projects = append(input.Projects, projectInfo{
						Number:      proj.Number,
						Title:       proj.Title,
						Description: proj.Description,
					})
				}
			}

			if len(input.Projects) != tt.expectedCount {
				t.Errorf("expected %d projects to classify, got %d",
					tt.expectedCount, len(input.Projects))
			}
		})
	}
}

func TestProjectCategories(t *testing.T) {
	// Document expected categories
	validCategories := []string{"supply", "task", "infrastructure", "operations", "other"}

	for _, category := range validCategories {
		t.Run(category, func(t *testing.T) {
			// Categories should be non-empty lowercase strings
			if category == "" {
				t.Error("category should not be empty")
			}
		})
	}
}

Graph