package httpserver

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

type Middleware http.HandlerFunc

func Authenticated(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Perform authentication here
		// For example, check for a valid token in the request header
		token := r.Header.Get("Authorization")
		if token == "" {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}

		// If authentication is successful, call the next handler
		next.ServeHTTP(w, r)
	})
}

type LoggingMiddleware struct {
	logger *log.Logger
}

func NewLoggingMiddleware(logger *log.Logger) *LoggingMiddleware {
	return &LoggingMiddleware{logger: logger}
}

func (m *LoggingMiddleware) Logging(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		next.ServeHTTP(w, r)
		m.logger.Println("Request:", r.Method, r.URL.Path, "Duration:", time.Since(start))
	})
}

type Timeout struct {
	Timeout time.Duration
}

func (m *Timeout) TimeoutMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx, cancel := context.WithTimeout(r.Context(), m.Timeout)
		defer cancel()

		r = r.WithContext(ctx)

		ch := make(chan struct{})
		defer close(ch)
		//
		go func() {
			next.ServeHTTP(w, r)
			ch <- struct{}{}
		}()

		select {
		case <-ch:
			// Request completed within timeout
		case <-ctx.Done():
			// Request timed out
			http.Error(w, "Request timed out", http.StatusGatewayTimeout)
		}
	})
}

func NewTimeout(timeout time.Duration) *Timeout {
	return &Timeout{Timeout: timeout}
}
