package logging

import (
	"log"
	"log/slog"
	"strings"
)

// Go starts a managed goroutine root. A panic is recorded through the same
// ERROR pipeline (which flushes file buffers) and then re-panicked so the
// process still fails fast.
func Go(logger *slog.Logger, run func()) {
	if logger == nil {
		logger = slog.Default()
	}
	go func() {
		defer RecoverPanic(logger)
		run()
	}()
}

// HTTPErrorLog bridges net/http's internal errors and recovered handler panics
// into the operational ERROR pipeline. Panic values are intentionally omitted;
// only the original runtime stack is retained.
func HTTPErrorLog(logger *slog.Logger) *log.Logger {
	if logger == nil {
		logger = slog.Default()
	}
	return log.New(httpErrorWriter{logger: logger}, "", 0)
}

type httpErrorWriter struct {
	logger *slog.Logger
}

func (writer httpErrorWriter) Write(data []byte) (int, error) {
	detail := strings.TrimSpace(string(data))
	if strings.HasPrefix(detail, "http: panic serving ") || strings.HasPrefix(detail, "http2: panic serving ") {
		stack := "unavailable"
		if _, runtimeStack, found := strings.Cut(detail, "\n"); found {
			stack = runtimeStack
		}
		writer.logger.Error("http handler panic recovered", slog.String("stacktrace", stack))
	} else {
		writer.logger.Error("http server error")
	}
	return len(data), nil
}
