package handlers

import (
	"log"
	"net/http"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

const defaultSystemdUnit = "sproutclaw-web.service"

func handleRestart() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"ok": true})
		go func() {
			time.Sleep(300 * time.Millisecond)
			if unit, underSystemd := systemdServiceUnit(); underSystemd {
				log.Printf("[restart] restarting via systemctl: %s", unit)
				cmd := exec.Command("systemctl", "restart", unit)
				out, err := cmd.CombinedOutput()
				if err != nil {
					log.Printf("[restart] systemctl restart failed: %v: %s", err, strings.TrimSpace(string(out)))
				}
				return
			}
			restartByReexec()
		}()
	}
}

func restartByReexec() {
	exe, err := os.Executable()
	if err != nil {
		log.Printf("[restart] get executable: %v", err)
		os.Exit(1)
	}
	cmd := exec.Command(exe, os.Args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		log.Printf("[restart] start new process: %v", err)
		os.Exit(1)
	}
	os.Exit(0)
}

func systemdServiceUnit() (string, bool) {
	if runtime.GOOS != "linux" {
		return "", false
	}
	if os.Getenv("INVOCATION_ID") == "" && !inSystemdCgroup() {
		return "", false
	}
	if unit := strings.TrimSpace(os.Getenv("SPROUTCLAW_WEB_SYSTEMD_UNIT")); unit != "" {
		return normalizeSystemdUnit(unit), true
	}
	if unit := readSystemdUnitFromCgroup(); unit != "" {
		return unit, true
	}
	return defaultSystemdUnit, true
}

func normalizeSystemdUnit(name string) string {
	if strings.HasSuffix(name, ".service") {
		return name
	}
	return name + ".service"
}

func inSystemdCgroup() bool {
	data, err := os.ReadFile("/proc/self/cgroup")
	if err != nil {
		return false
	}
	return strings.Contains(string(data), ".service")
}

func readSystemdUnitFromCgroup() string {
	data, err := os.ReadFile("/proc/self/cgroup")
	if err != nil {
		return ""
	}
	for _, line := range strings.Split(string(data), "\n") {
		idx := strings.LastIndex(line, "/")
		if idx < 0 {
			continue
		}
		name := line[idx+1:]
		if strings.HasSuffix(name, ".service") {
			return name
		}
	}
	return ""
}
