package server

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

// withRequestLog wraps h with access logging: one Info line per completed
// request carrying method, request URI, status, response size, and duration.
//
// Long-lived connections (the /logs stream) log once, at stream end.
func withRequestLog(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		rec := &recordingWriter{ResponseWriter: w, status: http.StatusOK}
		start := time.Now()
		defer func() {
			slog.Info("http request",
				"method", r.Method,
				"uri", r.URL.RequestURI(),
				"status", rec.status,
				"bytes", rec.bytes,
				"duration", time.Since(start),
			)
		}()
		h.ServeHTTP(rec, r)
	})
}

// recordingWriter captures the response status and byte count for access
// logging. Flush is forwarded so chunked streaming endpoints keep working
// through the wrapper.
type recordingWriter struct {
	http.ResponseWriter
	status int
	bytes  int
	wrote  bool
}

// WriteHeader records the first status; later calls do not overwrite it.
func (w *recordingWriter) WriteHeader(status int) {
	if !w.wrote {
		w.status = status
		w.wrote = true
	}
	w.ResponseWriter.WriteHeader(status)
}

func (w *recordingWriter) Write(p []byte) (int, error) {
	w.wrote = true
	n, err := w.ResponseWriter.Write(p)
	w.bytes += n
	return n, err
}

func (w *recordingWriter) Flush() {
	if f, ok := w.ResponseWriter.(http.Flusher); ok {
		f.Flush()
	}
}
