package httphandlers

import (
	"encoding/base64"
	"net/http"
	"net/url"
	"path"
	"strings"

	httpSwagger "github.com/swaggo/http-swagger"

	"github.com/fiskerinc/cloud-services/pkg/logger"
	"github.com/fiskerinc/cloud-services/pkg/utils/envtool"
)

var swaggerHandler func(http.ResponseWriter, *http.Request)
var username = envtool.GetEnv("SWAGGER_USERNAME", "")
var password = envtool.GetEnv("SWAGGER_PASSWORD", "")

func GetSwaggerHandler() http.HandlerFunc {
	swaggerHandler = httpSwagger.Handler()

	return swaggerDocs
}

func swaggerDocs(w http.ResponseWriter, r *http.Request) {
	logger.Info().Msgf("SwaggerDocs %s %s", r.Method, r.RequestURI)

	if username != "" && password != "" && !basicAuth(username, password, w, r) {
		return
	}

	if redirectToDocs(w, r) {
		return
	}

	swaggerHandler(w, r)
}

func basicAuth(username, password string, w http.ResponseWriter, r *http.Request) bool {
	auth := r.Header.Get("Authorization")
	if auth == "" {
		w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("401 Unauthorized\n"))
		return false
	}

	credentials, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("400 Bad Request\n"))
		return false
	}

	parts := strings.SplitN(string(credentials), ":", 2)
	if len(parts) != 2 || parts[0] != username || parts[1] != password {
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("401 Unauthorized\n"))
		return false
	}
	return true
}

func redirectToDocs(w http.ResponseWriter, r *http.Request) bool {
	url := shouldRedirect(r)
	if url == "" {
		return false
	}

	http.Redirect(w, r, url, http.StatusMovedPermanently)
	return true
}

func shouldRedirect(r *http.Request) string {
	u, err := url.Parse(r.RequestURI)
	if err != nil {
		logger.Error().Err(err).Send()
	}
	if strings.HasSuffix(u.Path, ".html") || strings.HasSuffix(u.Path, ".json") || strings.HasSuffix(u.Path, ".js") || strings.HasSuffix(u.Path, ".css") {
		return ""
	}

	return path.Join(u.Path, "index.html")
}
