package grpc

import (
	"context"
	"fmt"
	"github.com/UpmeshLTD/urus-aio/shipment/config"
	shipmentLog "github.com/UpmeshLTD/urus-aio/shipment/log"
	"github.com/UpmeshLTD/urus-aio/shipment/server/grpc/pb"
	"github.com/UpmeshLTD/urus-aio/shipment/service"
	"go.opencensus.io/plugin/ocgrpc"
	"google.golang.org/grpc"
	"log"
	"net"
)

//go:generate mockery --name=Server --inpackage --case=snake
type Server interface {
	Serve() error
}

func NewServer(
	svc service.Service,
	cfg config.Config,
	logger shipmentLog.Logger,
) Server {
	return &serverImpl{
		svc:    svc,
		cfg:    cfg,
		logger: logger,
	}
}

type serverImpl struct {
	svc    service.Service
	cfg    config.Config
	logger shipmentLog.Logger
}

func (i *serverImpl) Serve() error {

	conf := i.cfg.GetGRPCConfig()
	grpcListener, err := net.Listen("tcp", fmt.Sprintf(":%d", conf.Port))
	if err != nil {
		log.Printf("Listen GRPC error: %s", err.Error())
		return err
	}

	s := grpc.NewServer(
		grpc.StatsHandler(
			&ocgrpc.ServerHandler{},
		),
	)

	pb.RegisterShipmentServiceServer(s, &shipmentServer{
		svc: i.svc,
	})

	log.Printf(" 🚀 Listening GRPC on port %d", conf.Port)
	return s.Serve(grpcListener)
}

type shipmentServer struct {
	pb.UnimplementedShipmentServiceServer
	svc service.Service
}

func (i *shipmentServer) Ping(ctx context.Context, req *pb.PingRequest) (*pb.PingResponse, error) {
	return i.svc.GRPCPing(ctx, req)
}

func (i *shipmentServer) Archive(ctx context.Context, req *pb.ArchiveRequest) (*pb.ArchiveResponse, error) {
	return i.svc.GRPCArchive(ctx, req)
}

func (i *shipmentServer) ArchiveBatch(ctx context.Context, req *pb.ArchiveBatchRequest) (*pb.ArchiveBatchResponse, error) {
	return i.svc.GRPCArchiveBatch(ctx, req)
}

func (i *shipmentServer) SyncCourierShipmentStatus(ctx context.Context, req *pb.SyncCourierShipmentStatusRequest) (*pb.SyncCourierShipmentStatusResponse, error) {
	return i.svc.GRPCSyncCourierShipmentStatus(ctx, req)
}
