// Code generated by protoc-gen-slc. DO NOT EDIT.
package server

import (
	pb "bsm/full/module/base/feedback/pb"
	"context"
	"git.apinb.com/bsm-sdk/core/vars"
	gwRuntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/reflection"
	"google.golang.org/protobuf/proto"
	"net/http"
	"os"
	"strings"
	"time"
)

type Server struct {
	Grpc      *grpc.Server
	Ctx       context.Context
	Mux       *gwRuntime.ServeMux
	grpcConns map[string]*grpc.ClientConn // 连接池
}

func New(addr string) *Server {
	srv := &Server{
		Ctx:       context.Background(),
		Grpc:      grpc.NewServer(),
		Mux:       gwRuntime.NewServeMux(gwRuntime.WithForwardResponseRewriter(responseEnvelope)),
		grpcConns: make(map[string]*grpc.ClientConn),
	}

	// register service to grpc.Server
	pb.RegisterMethodServer(srv.Grpc, NewMethodServer())

	reflection.Register(srv.Grpc)

	// 连接池: 只创建一次连接并复用
	conn, ok := srv.grpcConns[addr]
	if !ok {
		var err error
		conn, err = grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
		if err != nil {
			panic("failed to dial grpc server: " + err.Error())
		}
		srv.grpcConns[addr] = conn
	}

	// 将服务注册到Gateway

	if err := pb.RegisterMethodHandler(srv.Ctx, srv.Mux, conn); err != nil {
		panic("Failed to register Method handler: " + err.Error())
	}

	// Register services swagger
	srv.RegisterSwagger()

	return srv
}

// RegisterSwagger 注册swagger
func (s *Server) RegisterSwagger() {
	srvKey := strings.ToLower(vars.ServiceKey)
	s.Mux.HandlePath("GET", "/"+srvKey+".swagger.json", func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
		w.Header().Set("Content-Type", "application/json")
		bytes, err := os.ReadFile("./swagger/" + srvKey + ".swagger.json")
		if err != nil {
			w.WriteHeader(http.StatusNotFound)
			w.Write([]byte(err.Error()))
			return
		}
		w.Write(bytes)
		return

	})
}

// response envelope
func responseEnvelope(_ context.Context, response proto.Message) (interface{}, error) {
	name := string(response.ProtoReflect().Descriptor().Name())
	if name == "Status" || name == "Error" || name == "StatusReply" {
		return response, nil
	}
	return map[string]any{
		"code":    0,
		"message": vars.OK,
		"details": response,
		"timeseq": time.Now().Unix(),
	}, nil
}
