// codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/interface/http/middleware/middleware.go
package middleware

import (
	"context"
	"net/http"

	uc_user "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/usecase/user"
	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/security/jwt"
	"go.uber.org/zap"
)

type Middleware interface {
	Attach(fn http.HandlerFunc) http.HandlerFunc
	Shutdown(ctx context.Context)
}

type middleware struct {
	logger            *zap.Logger
	jwt               jwt.JWTProvider
	userGetByIDUseCase uc_user.UserGetByIDUseCase
}

func NewMiddleware(
	logger *zap.Logger,
	jwtp jwt.JWTProvider,
	uc1 uc_user.UserGetByIDUseCase,
) Middleware {
	logger = logger.With(zap.String("module", "maplefile"))
	logger = logger.Named("MapleFile Middleware")
	return &middleware{
		logger:             logger,
		jwt:                jwtp,
		userGetByIDUseCase: uc1,
	}
}

// Attach function attaches to HTTP router to apply for every API call.
func (mid *middleware) Attach(fn http.HandlerFunc) http.HandlerFunc {

	return func(w http.ResponseWriter, r *http.Request) {
		// Apply base middleware to all requests
		handler := mid.applyBaseMiddleware(fn)

		// Check if the path requires authentication
		if isProtectedPath(mid.logger, r.URL.Path) {

			// Apply auth middleware for protected paths
			handler = mid.PostJWTProcessorMiddleware(handler)
			handler = mid.JWTProcessorMiddleware(handler)
			// handler = mid.EnforceBlacklistMiddleware(handler)
		}

		handler(w, r)
	}
}

// Attach function attaches to HTTP router to apply for every API call.
func (mid *middleware) applyBaseMiddleware(fn http.HandlerFunc) http.HandlerFunc {
	// Apply middleware in reverse order (bottom up)
	handler := fn
	handler = mid.URLProcessorMiddleware(handler)
	handler = mid.RequestBodySizeLimitMiddleware(handler)

	return handler
}

// RequestBodySizeLimitMiddleware limits the size of request bodies to prevent DoS attacks.
// Default limit is 10MB for most requests, which is sufficient for JSON metadata payloads.
func (mid *middleware) RequestBodySizeLimitMiddleware(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 10MB limit for request bodies
		// This is sufficient for JSON metadata while preventing abuse
		const maxBodySize = 10 * 1024 * 1024 // 10MB

		if r.Body != nil {
			r.Body = http.MaxBytesReader(w, r.Body, maxBodySize)
		}

		fn(w, r)
	}
}

// Shutdown shuts down the middleware.
func (mid *middleware) Shutdown(ctx context.Context) {
	// Log a message to indicate that the HTTP server is shutting down.
}
