//go:build darwin

package update

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
)

// Apply downloads the new binary and schedules replacement after exit (macOS).
func Apply(ctx context.Context, manifestURL string) (string, error) {
	latest, _, _, exe, tmp, err := prepareDownload(ctx, manifestURL)
	if err != nil {
		return "", err
	}
	_ = os.Chmod(tmp, 0o755)
	dir := filepath.Dir(exe)
	scriptPath := filepath.Join(dir, "navis-update.sh")
	pid := os.Getpid()

	script := "#!/bin/bash\n" +
		"set -e\n" +
		"EXE=" + shellQuote(exe) + "\n" +
		"NEW=" + shellQuote(tmp) + "\n" +
		"PID=" + strconv.Itoa(pid) + "\n" +
		"while kill -0 \"$PID\" 2>/dev/null; do sleep 0.4; done\n" +
		"sleep 0.5\n" +
		"mv -f \"$NEW\" \"$EXE\"\n" +
		"chmod +x \"$EXE\"\n" +
		"rm -f " + shellQuote(scriptPath) + "\n"

	if err := os.WriteFile(scriptPath, []byte(script), 0o755); err != nil {
		return "", err
	}
	cmd := exec.Command("/bin/bash", scriptPath)
	cmd.Dir = dir
	if err := cmd.Start(); err != nil {
		return "", fmt.Errorf("start updater: %w", err)
	}
	return latest, nil
}

func shellQuote(s string) string {
	return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
}
