package http_gateway

import (
	"common/log"
	"common/net/grpc/service"
	"common/net/http/http_resp"
	"common/proto/ss/grpc_pb"
	"context"
	"gateway/internal/handler/http_handler"
	"gateway/internal/net/http_gateway/wrapper"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/protobuf/encoding/protojson"
)

func InitServeMux() *runtime.ServeMux {
	baseMarshaler := &runtime.JSONPb{
		MarshalOptions: protojson.MarshalOptions{
			UseProtoNames:   false,
			EmitUnpopulated: true,
		},
		UnmarshalOptions: protojson.UnmarshalOptions{
			DiscardUnknown: true,
		},
	}
	unifiedMarshaler := wrapper.NewWrappedMarshaler(baseMarshaler)

	mux := runtime.NewServeMux(
		runtime.WithMarshalerOption(runtime.MIMEWildcard, unifiedMarshaler),
		runtime.WithErrorHandler(wrapper.ErrorHandler),
		runtime.WithIncomingHeaderMatcher(func(header string) (string, bool) {
			if header == "X-Usn" {
				return "X-Usn", true
			}
			return runtime.DefaultHeaderMatcher(header)
		}),
	)
	return mux
}

func InitRouter() *gin.Engine {
	gin.SetMode(gin.ReleaseMode)

	r := gin.New()
	r.Use(
		gin.Recovery(),
		ginLogger(log.GetLogger().Named("GIN")),
		cors.New(corsConfig()),
	)

	r.HandleMethodNotAllowed = true
	r.NoMethod(func(c *gin.Context) {
		http_resp.JsonMethodNotAllowed(c)
	})
	r.NoRoute(func(c *gin.Context) {
		http_resp.JsonNotFound(c)
	})

	initBaseRoute(r.Group("/"))

	auth := r.Group("/")
	auth.Use(authJwt())

	// 用户中心
	initUserPath(auth)

	return r
}

func initBaseRoute(r *gin.RouterGroup) {
	g := r.Group("/gw")
	g.POST("/login", http_handler.Login)
	g.POST("/refresh_token", http_handler.RefreshToken)
	g.GET("/test", http_handler.Test)
}

func initUserPath(r *gin.RouterGroup) {
	g := r.Group("/user")
	client, err := service.UserNewClientLB()
	if err != nil {
		log.Errorf("get user conn failed: %v", err)
		return
	}

	gwMux := InitServeMux()
	if err = grpc_pb.RegisterUserHandlerClient(context.Background(), gwMux, client); err != nil {
		log.Errorf("RegisterUserHandlerClient err: %v", err)
		return
	}

	g.Any("/*path", gin.WrapH(gwMux))
}
