package runner

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

	"github.com/google/uuid"
)

type PHPRunner struct {
	TempDir string
}

func (r *PHPRunner) 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)

	filePath := filepath.Join(workDir, "script.php")
	if err := ioutil.WriteFile(filePath, []byte(code), 0644); err != nil {
		return nil, err
	}

	cmd := exec.CommandContext(ctx, "php", "script.php")
	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
}
