//go:build integration
// +build integration

package integration

import (
	"context"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/kubeasy-dev/kubeasy-cli/internal/deployer"
	"github.com/kubeasy-dev/kubeasy-cli/internal/devutils"
	"github.com/kubeasy-dev/kubeasy-cli/internal/validation"
	"github.com/kubeasy-dev/kubeasy-cli/test/helpers"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// TestDevWorkflow validates the dev challenge lifecycle: scaffold → apply → validate → clean.
// Uses envtest instead of a real Kind cluster.
func TestDevWorkflow(t *testing.T) {
	env := helpers.SetupEnvTest(t)
	ctx := context.Background()

	// Scaffold challenge directory in a temp working dir
	workDir := t.TempDir()
	slug := devutils.GenerateSlug("Dev E2E Test")
	require.Equal(t, "dev-e2e-test", slug)

	challengeDir := filepath.Join(workDir, slug)
	for _, dir := range []string{
		challengeDir,
		filepath.Join(challengeDir, "manifests"),
		filepath.Join(challengeDir, "policies"),
	} {
		require.NoError(t, os.MkdirAll(dir, 0755))
	}

	require.NoError(t, os.WriteFile(filepath.Join(challengeDir, "challenge.yaml"), []byte(`title: "Dev E2E Test"
description: "Integration test for dev workflow"
theme: "pods-containers"
type: "build"
difficulty: "easy"
estimatedTime: 10
initialSituation: ""
objective: "Deploy a working nginx pod"
ofTheWeek: false
starterFriendly: false
objectives:
  - key: "pod-ready"
    title: "Pod Ready"
    description: "The nginx pod should be running and ready"
    order: 1
    type: condition
    spec:
      target:
        kind: Pod
        labelSelector:
          app: dev-e2e-nginx
      checks:
        - type: Ready
          status: "True"
`), 0600))

	// Use a ConfigMap manifest — envtest has no Deployment controller
	require.NoError(t, os.WriteFile(filepath.Join(challengeDir, "manifests", "config.yaml"), []byte(`apiVersion: v1
kind: ConfigMap
metadata:
  name: dev-e2e-nginx-config
data:
  placeholder: "true"
`), 0600))

	t.Run("resolve-dir", func(t *testing.T) {
		oldWd, _ := os.Getwd()
		defer func() { _ = os.Chdir(oldWd) }()
		require.NoError(t, os.Chdir(workDir))

		dir, err := devutils.ResolveLocalChallengeDir(slug, "")
		require.NoError(t, err)
		assert.Contains(t, dir, slug)
	})

	t.Run("apply", func(t *testing.T) {
		err := deployer.DeployLocalChallenge(ctx, env.Clientset, env.DynamicClient, challengeDir, env.Namespace)
		require.NoError(t, err)

		_, err = env.Clientset.CoreV1().ConfigMaps(env.Namespace).Get(ctx, "dev-e2e-nginx-config", metav1.GetOptions{})
		require.NoError(t, err, "manifest should have been applied")
	})

	t.Run("validate", func(t *testing.T) {
		// envtest has no scheduler — create the pod directly and mark it Ready
		pod := env.CreatePod(&corev1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "dev-e2e-nginx",
				Namespace: env.Namespace,
				Labels:    map[string]string{"app": "dev-e2e-nginx"},
			},
			Spec: corev1.PodSpec{
				Containers: []corev1.Container{{Name: "nginx", Image: "nginx:1.25"}},
			},
		})
		env.SetPodReady(pod.Name)

		config, err := validation.LoadFromFile(filepath.Join(challengeDir, "challenge.yaml"))
		require.NoError(t, err)
		require.NotEmpty(t, config.Validations)

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

		executor := validation.NewExecutor(env.Clientset, env.DynamicClient, env.Config, env.Namespace)
		results := executor.ExecuteAll(ctx, config.Validations)

		require.Len(t, results, len(config.Validations))
		for _, r := range results {
			assert.True(t, r.Passed, "validation %s should pass: %s", r.Key, r.Message)
		}
	})

	t.Run("clean", func(t *testing.T) {
		// CleanupChallenge also touches kubeconfig (SetNamespaceForContext), which is
		// irrelevant in envtest — test only the namespace deletion.
		err := env.Clientset.CoreV1().Namespaces().Delete(ctx, env.Namespace, metav1.DeleteOptions{})
		require.NoError(t, err, "namespace deletion should succeed")
	})
}
