/*
 * Copyright (C) 2023-2024
 * Das Land Schleswig-Holstein vertreten durch den
 * Ministerpräsidenten des Landes Schleswig-Holstein
 * Staatskanzlei
 * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 *
 * Lizenziert unter der EUPL, Version 1.2 oder - sobald
 * diese von der Europäischen Kommission genehmigt wurden -
 * Folgeversionen der EUPL ("Lizenz");
 * Sie dürfen dieses Werk ausschließlich gemäß
 * dieser Lizenz nutzen.
 * Eine Kopie der Lizenz finden Sie hier:
 *
 * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 *
 * Sofern nicht durch anwendbare Rechtsvorschriften
 * gefordert oder in schriftlicher Form vereinbart, wird
 * die unter der Lizenz verbreitete Software "so wie sie
 * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
 * ausdrücklich oder stillschweigend - verbreitet.
 * Die sprachspezifischen Genehmigungen und Beschränkungen
 * unter der Lizenz sind dem Lizenztext zu entnehmen.
 */

package server

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

const HomeUrlPath = "/"

type logResponseWriter struct {
	http.ResponseWriter
	statusCode int
}

func (rsp *logResponseWriter) WriteHeader(statusCode int) {
	rsp.statusCode = statusCode
	rsp.ResponseWriter.WriteHeader(statusCode)
}

func RequestLoggingMiddleware(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == HomeUrlPath {
			h.ServeHTTP(w, r)
			return
		}

		body, err := io.ReadAll(r.Body)
		if err != nil {
			log..WithError(err).Error("failed to read %v request body for %v: %v", r.Method, r.URL.Path, err)
			http.Error(w, fmt.Sprintf("failed to read request body: %v", err), http.StatusBadRequest)
			return
		}
		r.Body = io.NopCloser(bytes.NewReader(body))

		log.Debug("received %v request for %v with body: %v", r.Method, r.URL.Path, string(body))

		lw := &logResponseWriter{w, http.StatusOK}
		h.ServeHTTP(lw, r)

		if lw.statusCode == http.StatusOK {
			log.Debug("successfully handled %v request for %v with body: %v", r.Method, r.URL.Path, string(body))
		} else {
			log.Error("failed handling %v request for %v with body: %v, status code: %d", r.Method, r.URL.Path, string(body), lw.statusCode)
		}
	})
}