package router

import (
	"context"
	"net/http"
	"os"
	"simple-cluster-node/health"

	"github.com/google/uuid"
	"github.com/gorilla/mux"
	log "gitlab.com/gdulai/simpleloglvl"
)

func SetupRouter() *mux.Router {
	r := mux.NewRouter()
	r.Use(identifyRequest, corsCheck, logRequest)
	r.HandleFunc("/health", health.Handle).Methods("GET", "OPTIONS")

	/*
		r.HandleFunc("/album", handler.GetAlbums).Methods("GET", "OPTIONS")
		r.HandleFunc("/album", handler.SaveAlbum).Methods("POST", "OPTIONS")
		r.HandleFunc("/album/{albumId}", handler.DeleteAlbum).Methods("DELETE", "OPTIONS")
		r.HandleFunc("/album/{albumId}", handler.GetAlbum).Methods("GET", "OPTIONS")
		r.HandleFunc("/shareAlbum/{albumId}/{userId}", handler.ShareAlbum).Methods("POST", "OPTIONS")
	*/

	return r
}

func identifyRequest(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requestId, err := uuid.NewRandom()
		if err != nil {
			log.LogInfo("Failed to generated requestId!")
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		log.LogInfo("Assigned UUID to request! (%s)", &requestId)
		context := context.WithValue(r.Context(), "requestId", requestId)

		log.LogDebug("Next handler called! (%s)", requestId)

		next.ServeHTTP(w, r.WithContext(context))
	})
}

func corsCheck(handler http.Handler) http.Handler {
	origins := os.Getenv("CORS_ORIGINS")
	methods := os.Getenv("CORS_METHODS")
	header := os.Getenv("CORS_HEADERS")

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requestId := r.Context().Value("requestId")

		log.LogInfo("CORS check called... (%s)", requestId)

		w.Header().Set("Access-Control-Allow-Origin", origins)
		w.Header().Set("Access-Control-Allow-Methods", methods)
		w.Header().Set("Access-Control-Allow-Headers", header)

		if r.Method == http.MethodOptions {
			log.LogInfo("Pre flight check OK! (%s)", requestId)

			w.WriteHeader(http.StatusOK)
			return
		}

		log.LogDebug("Next handler called! (%s)", requestId)
		handler.ServeHTTP(w, r)
	})
}

func logRequest(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requestId := r.Context().Value("requestId")

		log.LogInfo("%s %s %s from %s (%s)", r.Method, r.RequestURI, r.Proto, r.RemoteAddr, r.Context().Value("requestId"))
		log.LogDebug("Next handler called! (%s)", requestId)

		next.ServeHTTP(w, r)
	})
}
