// +build integration

package tests

import (
	"context"
	"encoding/json"
	"os"
	"testing"
	"time"

	"github.com/rockliang/poimen/workflows/internal/routing"
	"github.com/stretchr/testify/require"
)

// TestRoutingE2E_GenerateAndValidate tests full flow against real api.riotpiao.com
// Run with: go test -tags=integration -v -run TestRoutingE2E ./tests/...
func TestRoutingE2E_GenerateAndValidate(t *testing.T) {
	if os.Getenv("RUN_INTEGRATION_TESTS") != "1" {
		t.Skip("Skipping integration test. Set RUN_INTEGRATION_TESTS=1 to run.")
	}

	// Load knowledge base
	kb, err := routing.LoadKnowledgeBaseFromDefaultPath()
	require.NoError(t, err, "failed to load knowledge base")

	// Create router
	router, err := routing.NewLLMRouter(kb)
	require.NoError(t, err, "failed to create router")

	// Create validator
	validator := routing.NewValidator(kb)

	tests := []struct {
		name    string
		message string
		context map[string]interface{}
		isCron  bool
	}{
		{
			name:    "one-time repo analysis",
			message: "Analyze https://github.com/rockliang/poimen for code quality and security issues",
			context: map[string]interface{}{"branch": "main"},
			isCron:  false,
		},
		{
			name:    "scheduled security scan",
			message: "Run daily security scan at 3 AM on https://github.com/rockliang/poimen",
			isCron:  true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
			defer cancel()

			// Generate workflow spec
			input := routing.LLMRouterInput{
				Message: tt.message,
				Context: tt.context,
			}

			output, err := router.Route(ctx, input)
			require.NoError(t, err, "LLM router failed")

			// Log generated spec
			specJSON, _ := json.MarshalIndent(output, "", "  ")
			t.Logf("Generated spec:\n%s", string(specJSON))

			// Validate based on type
			if tt.isCron {
				require.True(t, output.IsCron, "expected cron workflow")
				require.NotNil(t, output.CronSpec, "cron spec is nil")
				require.NotEmpty(t, output.CronSpec.Schedule, "cron schedule is empty")

				result := validator.ValidateCronWorkflowSpec(output.CronSpec)
				require.True(t, result.Valid, "validation failed: %v", result.Errors)

				t.Logf("Cron workflow validated: %s (schedule: %s)", 
					output.CronSpec.Name, output.CronSpec.Schedule)
			} else {
				require.False(t, output.IsCron, "expected one-time workflow")
				require.NotNil(t, output.Spec, "spec is nil")

				result := validator.ValidateWorkflowSpec(output.Spec)
				require.True(t, result.Valid, "validation failed: %v", result.Errors)

				t.Logf("One-time workflow validated: %s (%d states)", 
					output.Spec.Name, len(output.Spec.States))
			}
		})
	}
}

// TestRoutingE2E_FullPipeline tests LLM router -> validation -> (simulated) execution
func TestRoutingE2E_FullPipeline(t *testing.T) {
	if os.Getenv("RUN_INTEGRATION_TESTS") != "1" {
		t.Skip("Skipping integration test. Set RUN_INTEGRATION_TESTS=1 to run.")
	}

	kb, err := routing.LoadKnowledgeBaseFromDefaultPath()
	require.NoError(t, err)

	router, err := routing.NewLLMRouter(kb)
	require.NoError(t, err)

	validator := routing.NewValidator(kb)

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

	// Generate workflow
	output, err := router.Route(ctx, routing.LLMRouterInput{
		Message: "Clone and analyze https://github.com/rockliang/poimen for security vulnerabilities",
	})
	require.NoError(t, err)
	require.False(t, output.IsCron)
	require.NotNil(t, output.Spec)

	// Validate
	result := validator.ValidateWorkflowSpec(output.Spec)
	require.True(t, result.Valid, "validation failed: %v", result.Errors)

	// Verify structure
	require.NotEmpty(t, output.Spec.Name)
	require.NotEmpty(t, output.Spec.States)

	// First state should be CloneRepoActivity
	require.Equal(t, "CloneRepoActivity", output.Spec.States[0].Resource,
		"expected first activity to be CloneRepoActivity")

	// Check that flaky activities have retry policies
	for _, state := range output.Spec.States {
		if state.Type == routing.StateTypeTask {
			if kb.IsFlaky(state.Resource) {
				require.NotNil(t, state.Retry, "flaky activity %s should have retry policy", state.Resource)
				require.GreaterOrEqual(t, state.Retry.MaxAttempts, int32(2), 
					"flaky activity %s should have at least 2 retries", state.Resource)
			}
		}
	}

	t.Logf("Full pipeline test passed: %s with %d states", output.Spec.Name, len(output.Spec.States))
}
