package rest

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"strings"
)

func (s *Server) handleRouteDecisionTree(w http.ResponseWriter, r *http.Request) {
	s.proxyRouteTreeEndpoint(w, r, "/api/v1/routes/tree")
}

func (s *Server) handleRouteDepth(w http.ResponseWriter, r *http.Request) {
	s.proxyRouteTreeEndpoint(w, r, "/api/v1/routes/depth")
}

func (s *Server) proxyRouteTreeEndpoint(w http.ResponseWriter, r *http.Request, path string) {
	if r.Method != http.MethodGet {
		writeMethodNotAllowed(w)
		return
	}

	baseURL := strings.TrimSpace(firstNonEmptyEnv(
		"TOKEN_AGGREGATION_API_BASE",
		"TOKEN_AGGREGATION_URL",
		"TOKEN_AGGREGATION_BASE_URL",
	))
	if baseURL == "" {
		writeError(w, http.StatusServiceUnavailable, "service_unavailable", "token aggregation api base url is not configured")
		return
	}

	target, err := url.Parse(strings.TrimRight(baseURL, "/"))
	if err != nil {
		writeError(w, http.StatusBadGateway, "bad_gateway", fmt.Sprintf("invalid token aggregation api base url: %v", err))
		return
	}

	proxy := httputil.NewSingleHostReverseProxy(target)
	originalDirector := proxy.Director
	proxy.Director = func(req *http.Request) {
		originalDirector(req)
		req.URL.Path = joinProxyPath(target.Path, path)
		req.URL.RawPath = req.URL.Path
	}
	proxy.ErrorHandler = func(rw http.ResponseWriter, req *http.Request, proxyErr error) {
		writeError(rw, http.StatusBadGateway, "bad_gateway", fmt.Sprintf("route tree proxy failed for %s: %v", path, proxyErr))
	}

	proxy.ServeHTTP(w, r)
}

func joinProxyPath(basePath, path string) string {
	switch {
	case strings.HasSuffix(basePath, "/") && strings.HasPrefix(path, "/"):
		return basePath + path[1:]
	case !strings.HasSuffix(basePath, "/") && !strings.HasPrefix(path, "/"):
		return basePath + "/" + path
	default:
		return basePath + path
	}
}

func firstNonEmptyEnv(keys ...string) string {
	for _, key := range keys {
		if value := strings.TrimSpace(os.Getenv(key)); value != "" {
			return value
		}
	}
	return ""
}
