package executil

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"

	"zlh-agent/scripts"
)

// RunEmbeddedScript executes an embedded script via bash by piping its contents to stdin.
// If the script is a devcontainer installer, this automatically prepends the shared common.sh
// so that tiny per-runtime installers can call install_runtime in the same shell session.
func RunEmbeddedScript(scriptPath string, extraEnv ...string) error {
	normalized := normalizeEmbeddedPath(scriptPath)

	payload, err := loadEmbeddedPayload(normalized)
	if err != nil {
		return err
	}

	cmd := exec.Command("bash")
	cmd.Stdin = bytes.NewReader(payload)

	// Inherit current env and overlay any provided vars (e.g., RUNTIME_VERSION=24).
	if len(extraEnv) > 0 {
		cmd.Env = append(os.Environ(), extraEnv...)
	}

	// Match RunScript behavior (executil.go)
	var buf bytes.Buffer
	cmd.Stdout = io.MultiWriter(os.Stdout, &buf)
	cmd.Stderr = io.MultiWriter(os.Stderr, &buf)
	log.Printf("[provision] action=run_embedded_script path=%s", normalized)

	if err := cmd.Run(); err != nil {
		log.Printf("[provision] action=run_embedded_script status=failed path=%s err=%v", normalized, err)
		for _, line := range tailLogLines(buf.String(), 10) {
			log.Printf("[provision] path=%s output=%s", normalized, line)
		}
		return err
	}
	log.Printf("[provision] action=run_embedded_script status=ok path=%s", normalized)
	return nil
}

func loadEmbeddedPayload(normalized string) ([]byte, error) {
	// If this is a devcontainer installer, prepend the shared library.
	if strings.HasPrefix(normalized, "devcontainer/") {
		commonPath := "devcontainer/lib/common.sh"
		common, err := scripts.FS.ReadFile(commonPath)
		if err != nil {
			return nil, fmt.Errorf("embedded script missing: %s: %w", commonPath, err)
		}

		body, err := scripts.FS.ReadFile(normalized)
		if err != nil {
			return nil, fmt.Errorf("embedded script missing: %s: %w", normalized, err)
		}

		// Ensure bash sees common first, then runtime installer.
		return append(append(common, '\n'), body...), nil
	}

	data, err := scripts.FS.ReadFile(normalized)
	if err != nil {
		return nil, fmt.Errorf("embedded script missing: %s: %w", normalized, err)
	}
	return data, nil
}

func normalizeEmbeddedPath(p string) string {
	p = strings.TrimPrefix(p, "scripts/")
	p = path.Clean(p)
	return strings.TrimPrefix(p, "/")
}
