package proxy

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	"go.uber.org/zap"
)

const (
	ProxyBasePath       = "proxy"
	TiBRServiceBasePath = "tibr"
)

var backends = map[string]proxyHandler{
	TiBRServiceBasePath: tibrHandler,
	// add other services...
}

type proxyHandler func(w http.ResponseWriter, r *http.Request, handlerPath string)

// Notice:
// 1. If client vist cluster agent for proxy through the kong ingress, the path should be like: /cluster-agent/{namespace}/proxy/{service_name}/{service_handler_path}
// 2. If client visit cluster agent for proxy directly, the path should be like: /proxy/{service_name}/{service_handler_path}
func ProxyEntry(c *gin.Context) {
	proxyPath := c.Request.URL.Path
	log.Info("proxy request received", zap.Any("proxy path", proxyPath))
	parts := strings.SplitN(strings.TrimPrefix(proxyPath, "/"), "/", 2)
	if len(parts) < 2 {
		log.Warn("invalid proxy path", zap.Any("expected", "/{service_name}/{service_handler_path}"), zap.Any("actual", proxyPath))
		c.String(http.StatusBadRequest, "invalid path: expected /{service_name}/{service_handler_path} but got %s", proxyPath)
		return
	}
	serviceBasePath, handlerPath := parts[0], parts[1]
	log.Info("proxy path parsed", zap.Any("serviceBasePath", serviceBasePath), zap.Any("handlerPath", handlerPath))

	handler, ok := backends[serviceBasePath]
	if !ok {
		log.Warn("unknown service", zap.Any("service", serviceBasePath))
		c.String(http.StatusNotFound, "unknown service: %s", serviceBasePath)
		return
	}

	log.Info("service found, handover to the handler", zap.Any("service", serviceBasePath))
	handler(c.Writer, c.Request, handlerPath)
}
