package runner

import (
	"bytes"
	"context"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/google/uuid"
)

type GoRunner struct {
	TempDir string
}

func (r *GoRunner) Run(ctx context.Context, code string) (*ExecutionResult, error) {
	// 创建唯一的工作目录
	workDir := filepath.Join(r.TempDir, uuid.New().String())
	if err := os.MkdirAll(workDir, 0755); err != nil {
		return nil, err
	}
	defer os.RemoveAll(workDir) // 清理

	// 写入main.go
	// 注意：这里假设代码是一个完整的package main
	// 如果用户只提供了函数片段，可能需要包装。这里假设是完整代码。
	filePath := filepath.Join(workDir, "main.go")
	if err := ioutil.WriteFile(filePath, []byte(code), 0644); err != nil {
		return nil, err
	}

	// 准备命令
	// 使用 go run 运行
	cmd := exec.CommandContext(ctx, "go", "run", "main.go")
	cmd.Dir = workDir

	// 捕获输出
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	startTime := time.Now()
	err := cmd.Run()
	duration := time.Since(startTime).Milliseconds()

	result := &ExecutionResult{
		Output:   stdout.String(),
		Error:    stderr.String(),
		Duration: duration,
	}

	if err != nil {
		if exitErr, ok := err.(*exec.ExitError); ok {
			result.ExitCode = exitErr.ExitCode()
		} else {
			result.ExitCode = -1
		}
		// 如果是超时
		if ctx.Err() == context.DeadlineExceeded {
			result.Error += "\nExecution timed out"
		}
	}

	return result, nil
}
