package grpcclientmdl

import (
	"context"
	"errors"
	"time"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/grpcbuildermdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
	grpcpool "github.com/processout/grpc-go-pool"
	"google.golang.org/grpc"
)

// type GRPCHost struct {
// 	Host string `json:"host"`
// 	Port string `json:"port"`
// }

// var clientConns map[string]*grpc.ClientConn
// var mutex sync.Mutex
// var once sync.Once

// // GetGRPCClientConnection GetGRPCClientConnection
// func GetGRPCClientConnection(hostName string) (*grpc.ClientConn, error) {
// 	defer mutex.Unlock()
// 	mutex.Lock()
// 	if clientConns == nil {
// 		return nil, errormdl.Wrap("GRPC_NOT_DONE")
// 	}
// 	if hostName == "" {
// 		if instance, ok := clientConns[hostName]; ok {
// 			return instance, nil
// 		}
// 	}
// 	if instance, ok := clientConns[hostName]; ok {
// 		return instance, nil
// 	}
// 	return nil, errormdl.Wrap("GRPC not found for instance: " + hostName)
// }

// TotalCheck TotalCheck
func TotalCheck() (string, error) {
	// TODO: review
	conn, err := grpc.Dial("0.0.0.0:50051", grpc.WithInsecure())
	if err != nil {
		loggermdl.LogError("Could not connect: ", err)
	}
	defer conn.Close()
	c := grpcbuildermdl.NewGRPCCheckClient(conn)

	req := &grpcbuildermdl.GRPCRequest{}
	res, err := c.GRPCCheck(context.Background(), req)

	return res.GetData(), nil
}

type Employee struct {
	Name   string `json:"empname"`
	Number int    `json:"empid"`
}

var instances map[string]*grpcpool.Pool
var instancesList map[string]map[string]*grpcpool.Pool

// Init init
func Init(grpcServerURLList []string) {

	instances = make(map[string]*grpcpool.Pool)
	loggermdl.LogError("Length of grpcServerURLList", len(grpcServerURLList))

	for index := 0; index < len(grpcServerURLList); index++ {
		CreateConnection(grpcServerURLList[index])
	}
	loggermdl.LogError("instances", instances)
}

//ByteHandler ByteHandler
func ByteHandler(req *grpcbuildermdl.GRPCRequest, grpcServerURL string) ([]byte, error) {
	loggermdl.LogError("grpcServer instances", instances[grpcServerURL])
	if instances[grpcServerURL] != nil {
		conn, err := instances[grpcServerURL].Get(context.Background())
		if err != nil {
			loggermdl.LogError("Failed to create gRPC pool: %v", err)
			return nil, err
		}

		client := grpcbuildermdl.NewGRPCServiceClient(conn.ClientConn)

		res, err := client.GRPCHandler(context.Background(), req)
		if err != nil {
			loggermdl.LogError("GRPCHandler err:", err)
			return nil, err
		}
		return res.GetData(), nil
	}
	return []byte{}, errors.New("no grpc connection found")
}

// CreateConnection method
func CreateConnection(serverURL string) {
	var factory grpcpool.Factory
	// serverURL := grpcServerURLList[index]
	factory = func() (*grpc.ClientConn, error) {
		conn, err := grpc.Dial(serverURL, grpc.WithInsecure())
		if err != nil {
			loggermdl.LogError("Failed to start gRPC connection: %v", err)
		}
		loggermdl.LogError("Connected to server")
		return conn, err
	}

	pool, err := grpcpool.New(factory, 5, 5, time.Second)

	if err != nil {
		loggermdl.LogError("Failed to create gRPC pool: %v", err)
	}
	instances[serverURL] = pool
}