package api

import (
	"log"
	"net/http"
	"os"
	"time"
)

// restartDelay gives the in-flight HTTP response time to flush before the process exits.
const restartDelay = 500 * time.Millisecond

// gracefulSelfRestart schedules a clean process exit after a short delay. The container
// runs with `restart: unless-stopped`, so exiting 0 makes Docker start a fresh process
// that re-reads controller.yaml. This is how a config-apply (e.g. a rotated Cloudflare
// API token) and the manual restart button actually take effect: singletons such as the
// Cloudflare client are built once at startup and are not reloaded in-process.
func gracefulSelfRestart(logger *log.Logger) {
	GracefulSelfRestart(logger)
}

// GracefulSelfRestart is the exported entry point to the same graceful restart, so non-api callers
// (the config-refresh reconcile wired in main.go) reuse this one mechanism instead of reinventing an
// os.Exit path. See gracefulSelfRestart for the rationale.
func GracefulSelfRestart(logger *log.Logger) {
	go func() {
		time.Sleep(restartDelay)
		if logger != nil {
			logger.Println("[INFO] [api] Graceful self-restart: exiting (0) for container restart")
		}
		os.Exit(0)
	}()
}

// flushResponse flushes buffered output to the client if the writer supports it, so the
// caller receives the response body before a subsequent self-restart kills the process.
func flushResponse(w http.ResponseWriter) {
	if f, ok := w.(http.Flusher); ok {
		f.Flush()
	}
}

// selfRestart handles POST /api/selfrestart — a customer-facing self-serve restart so a
// user can recover the controller without rebooting the whole guest. Auth + CSRF are
// applied by the /api/ mux mount (same protection as every other state-changing endpoint).
// Responds first, flushes, then triggers the graceful restart.
func (r *Router) selfRestart(w http.ResponseWriter, _ *http.Request) {
	r.logger.Println("[INFO] [api] Manual controller restart requested")
	writeJSON(w, http.StatusOK, apiResponse{OK: true, Message: "Újraindítás folyamatban…"})
	flushResponse(w)
	if r.restart != nil {
		r.restart()
	}
}
