package server

import (
	"context"
	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
	grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"net"
	"gitea.pena/SQuiz/core/internal/initialize"
	"gitea.pena/SQuiz/core/internal/proto/notifyer"
	"time"
)

type GRPC struct {
	grpc   *grpc.Server
	logger *zap.Logger
}

func NewGRPC(logger *zap.Logger) (*GRPC, error) {
	grpcStreamInterceptor := grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
		grpc_zap.StreamServerInterceptor(logger),
		grpc_recovery.StreamServerInterceptor(),
	))

	grpcUnaryInterceptor := grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
		grpc_zap.UnaryServerInterceptor(logger),
		grpc_recovery.UnaryServerInterceptor(),
	))

	return &GRPC{
		grpc:   grpc.NewServer(grpcStreamInterceptor, grpcUnaryInterceptor, grpc.ConnectionTimeout(5*time.Second)),
		logger: logger,
	}, nil
}

func (g *GRPC) Run(connectionString string) {
	g.logger.Info("Starting GRPC Server", zap.String("host", connectionString))

	if err := g.listen(connectionString); err != nil && err != grpc.ErrServerStopped {
		g.logger.Error("GRPC Listen error", zap.Error(err))
	}
}

func (g *GRPC) Stop(_ context.Context) error {
	g.grpc.GracefulStop()
	g.logger.Info("Shutting down GRPC server...")

	return nil
}

func (g *GRPC) Register(reg initialize.GRpcControllers) *GRPC {
	notifyer.RegisterQuizServiceServer(g.grpc, reg.MailNotify)
	// another
	return g
}

func (g *GRPC) listen(address string) error {
	listener, err := net.Listen("tcp", address)
	if err != nil {
		return err
	}

	return g.grpc.Serve(listener)
}
