package composer

import (
	"context"
	"net/http"
	"testing"
	"time"
)

func TestOllamaClient_Generate(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	client := NewOllamaClient("llama3.1:8b")

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	prompt := "What is the capital of France? Respond with just the city name."

	response, err := client.Generate(ctx, prompt)
	if err != nil {
		t.Fatalf("Failed to generate response: %v", err)
	}

	if response == "" {
		t.Error("Expected non-empty response")
	}

	t.Logf("Ollama response: %s", response)
}

func TestTaskClassificationWithLLM(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	// Create test configuration with LLM enabled
	config := DefaultComposerConfig()
	config.FeatureFlags.EnableLLMClassification = true
	config.FeatureFlags.EnableAnalysisLogging = true
	config.FeatureFlags.EnableFailsafeFallback = true

	service := NewService(nil, config)

	testInput := &TaskAnalysisInput{
		Title:       "Fix Docker Client API compilation error in swarm_manager.go",
		Description: "The error is: undefined: types.ContainerLogsOptions. This needs to be fixed to allow proper compilation of the WHOOSH project.",
		Requirements: []string{
			"Fix compilation error",
			"Maintain backward compatibility",
			"Test the fix",
		},
		Priority:  PriorityHigh,
		TechStack: []string{"Go", "Docker", "API"},
	}

	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	startTime := time.Now()
	classification, err := service.classifyTaskWithLLM(ctx, testInput)
	duration := time.Since(startTime)

	if err != nil {
		t.Fatalf("LLM classification failed: %v", err)
	}

	// Verify classification results
	if classification == nil {
		t.Fatal("Expected non-nil classification")
	}

	if classification.TaskType == "" {
		t.Error("Expected task type to be set")
	}

	if classification.ComplexityScore < 0 || classification.ComplexityScore > 1 {
		t.Errorf("Expected complexity score between 0-1, got %f", classification.ComplexityScore)
	}

	if len(classification.PrimaryDomains) == 0 {
		t.Error("Expected at least one primary domain")
	}

	// Check performance requirement
	if duration > 5*time.Second {
		t.Errorf("Classification took %v, exceeds 5s requirement", duration)
	}

	t.Logf("Classification completed in %v", duration)
	t.Logf("Task Type: %s", classification.TaskType)
	t.Logf("Complexity: %.2f", classification.ComplexityScore)
	t.Logf("Primary Domains: %v", classification.PrimaryDomains)
	t.Logf("Risk Level: %s", classification.RiskLevel)
}

func TestSkillAnalysisWithLLM(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	// Create test configuration with LLM enabled
	config := DefaultComposerConfig()
	config.FeatureFlags.EnableLLMSkillAnalysis = true
	config.FeatureFlags.EnableAnalysisLogging = true
	config.FeatureFlags.EnableFailsafeFallback = true

	service := NewService(nil, config)

	testInput := &TaskAnalysisInput{
		Title:       "Implement LLM Integration for Team Composition Engine",
		Description: "Implement LLM-powered task classification and skill requirement analysis using Ollama API",
		Requirements: []string{
			"Connect to Ollama API",
			"Implement task classification",
			"Add error handling",
			"Support feature flags",
		},
		Priority:  PriorityHigh,
		TechStack: []string{"Go", "HTTP API", "LLM", "JSON"},
	}

	// Create a sample classification
	classification := &TaskClassification{
		TaskType:           TaskTypeFeatureDevelopment,
		ComplexityScore:    0.7,
		PrimaryDomains:     []string{"backend", "api", "ai"},
		SecondaryDomains:   []string{"integration"},
		EstimatedDuration:  8,
		RiskLevel:          "medium",
		RequiredExperience: "intermediate",
	}

	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	startTime := time.Now()
	skillRequirements, err := service.analyzeSkillRequirementsWithLLM(ctx, testInput, classification)
	duration := time.Since(startTime)

	if err != nil {
		t.Fatalf("LLM skill analysis failed: %v", err)
	}

	// Verify skill requirements results
	if skillRequirements == nil {
		t.Fatal("Expected non-nil skill requirements")
	}

	if len(skillRequirements.CriticalSkills) == 0 {
		t.Error("Expected at least one critical skill")
	}

	if skillRequirements.TotalSkillCount != len(skillRequirements.CriticalSkills)+len(skillRequirements.DesirableSkills) {
		t.Error("Total skill count mismatch")
	}

	// Check performance requirement
	if duration > 5*time.Second {
		t.Errorf("Skill analysis took %v, exceeds 5s requirement", duration)
	}

	t.Logf("Skill analysis completed in %v", duration)
	t.Logf("Critical Skills: %d", len(skillRequirements.CriticalSkills))
	t.Logf("Desirable Skills: %d", len(skillRequirements.DesirableSkills))
	t.Logf("Total Skills: %d", skillRequirements.TotalSkillCount)

	// Log first few skills for verification
	for i, skill := range skillRequirements.CriticalSkills {
		if i < 3 {
			t.Logf("Critical Skill %d: %s (proficiency: %.2f)", i+1, skill.Domain, skill.MinProficiency)
		}
	}
}

func TestLLMIntegrationFallback(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	// Create test configuration with LLM enabled but invalid endpoint
	config := DefaultComposerConfig()
	config.FeatureFlags.EnableLLMClassification = true
	config.FeatureFlags.EnableFailsafeFallback = true
	config.AnalysisTimeoutSecs = 1 // Very short timeout to trigger failure

	service := NewService(nil, config)

	// Override with a client that will fail
	service.ollamaClient = &OllamaClient{
		baseURL: "http://invalid-endpoint:99999",
		model:   "invalid-model",
		httpClient: &http.Client{
			Timeout: 1 * time.Second,
		},
	}

	testInput := &TaskAnalysisInput{
		Title:       "Test Task",
		Description: "This should fall back to heuristics",
		Priority:    PriorityLow,
		TechStack:   []string{"Go"},
	}

	ctx := context.Background()

	// This should fall back to heuristics when LLM fails
	classification, err := service.classifyTaskWithLLM(ctx, testInput)
	if err != nil {
		t.Fatalf("Expected fallback to succeed, got error: %v", err)
	}

	if classification == nil {
		t.Fatal("Expected classification result from fallback")
	}

	t.Logf("Fallback classification successful: %s", classification.TaskType)
}