package logreq

import (
	"time"

	"github.com/valyala/fasthttp"

	"gh.tarampamp.am/error-pages/internal/logger"
)

// New creates a middleware that logs every incoming request.
//
// The skipper function should return true if the request should be skipped. It's ok to pass nil.
func New(
	log *logger.Logger,
	skipper func(*fasthttp.RequestCtx) bool,
) func(fasthttp.RequestHandler) fasthttp.RequestHandler {
	return func(next fasthttp.RequestHandler) fasthttp.RequestHandler {
		return func(ctx *fasthttp.RequestCtx) {
			if skipper != nil && skipper(ctx) {
				next(ctx)

				return
			}

			var now = time.Now()

			defer func() {
				var fields = []logger.Attr{
					logger.Int("status code", ctx.Response.StatusCode()),
					logger.String("useragent", string(ctx.UserAgent())),
					logger.String("method", string(ctx.Method())),
					logger.String("url", string(ctx.RequestURI())),
					logger.String("referer", string(ctx.Referer())),
					logger.String("content type", string(ctx.Response.Header.ContentType())),
					logger.String("remote addr", ctx.RemoteAddr().String()),
					logger.Duration("duration", time.Since(now).Round(time.Microsecond)),
				}

				if log.Level() <= logger.DebugLevel {
					var (
						reqHeaders  = make(map[string]string)
						respHeaders = make(map[string]string)
					)

					ctx.Request.Header.VisitAll(func(key, value []byte) { reqHeaders[string(key)] = string(value) })
					ctx.Response.Header.VisitAll(func(key, value []byte) { respHeaders[string(key)] = string(value) })

					fields = append(fields,
						logger.Any("request headers", reqHeaders),
						logger.Any("response headers", respHeaders),
					)
				}

				log.Info("HTTP request processed", fields...)
			}()

			next(ctx)
		}
	}
}
