package skills

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

func TestExecutor(t *testing.T) {
	tmpDir := t.TempDir()

	// Create a simple bash script
	scriptPath := filepath.Join(tmpDir, "test.sh")
	scriptContent := `#!/bin/bash
echo "Hello from script"
echo "Args: $@"
`
	if err := os.WriteFile(scriptPath, []byte(scriptContent), 0755); err != nil {
		t.Fatal(err)
	}

	// Create a script that times out
	timeoutScriptPath := filepath.Join(tmpDir, "timeout.sh")
	timeoutContent := `#!/bin/bash
sleep 10
`
	if err := os.WriteFile(timeoutScriptPath, []byte(timeoutContent), 0755); err != nil {
		t.Fatal(err)
	}

	// Create a failing script
	failScriptPath := filepath.Join(tmpDir, "fail.sh")
	failContent := `#!/bin/bash
exit 1
`
	if err := os.WriteFile(failScriptPath, []byte(failContent), 0755); err != nil {
		t.Fatal(err)
	}

	executor := NewExecutor([]string{"bash", "sh"}, 2*time.Second)

	// Test successful execution
	t.Run("successful_execution", func(t *testing.T) {
		ctx := context.Background()
		output, err := executor.Run(ctx, scriptPath, []string{"arg1", "arg2"})
		if err != nil {
			t.Fatalf("Run failed: %v", err)
		}

		if !strings.Contains(output, "Hello from script") {
			t.Errorf("expected 'Hello from script' in output, got: %q", output)
		}

		if !strings.Contains(output, "Args: arg1 arg2") {
			t.Errorf("expected 'Args: arg1 arg2' in output, got: %q", output)
		}
	})

	// Test timeout
	t.Run("timeout", func(t *testing.T) {
		ctx := context.Background()
		_, err := executor.Run(ctx, timeoutScriptPath, nil)
		if err == nil {
			t.Error("expected timeout error")
		}

		if !strings.Contains(err.Error(), "timeout") {
			t.Errorf("expected timeout error, got: %v", err)
		}
	})

	// Test script failure
	t.Run("script_failure", func(t *testing.T) {
		ctx := context.Background()
		_, err := executor.Run(ctx, failScriptPath, nil)
		if err == nil {
			t.Error("expected script failure error")
		}
	})

	// Test disallowed interpreter
	t.Run("disallowed_interpreter", func(t *testing.T) {
		pyScriptPath := filepath.Join(tmpDir, "test.py")
		pyContent := `#!/usr/bin/env python3
print("hello")
`
		if err := os.WriteFile(pyScriptPath, []byte(pyContent), 0755); err != nil {
			t.Fatal(err)
		}

		ctx := context.Background()
		_, err := executor.Run(ctx, pyScriptPath, nil)
		if err == nil {
			t.Error("expected error for disallowed interpreter")
		}

		if !strings.Contains(err.Error(), "not allowed") {
			t.Errorf("expected 'not allowed' error, got: %v", err)
		}
	})

	// Test allowed python interpreter
	t.Run("allowed_python", func(t *testing.T) {
		pyExecutor := NewExecutor([]string{"python3"}, 2*time.Second)

		pyScriptPath := filepath.Join(tmpDir, "hello.py")
		pyContent := `#!/usr/bin/env python3
print("Hello from Python")
`
		if err := os.WriteFile(pyScriptPath, []byte(pyContent), 0755); err != nil {
			t.Fatal(err)
		}

		ctx := context.Background()
		output, err := pyExecutor.Run(ctx, pyScriptPath, nil)
		if err != nil {
			t.Fatalf("Run failed: %v", err)
		}

		if !strings.Contains(output, "Hello from Python") {
			t.Errorf("expected 'Hello from Python' in output, got: %q", output)
		}
	})
}
