package grpcli

import (
	"context"
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	"github.com/tidbcloud/metrics-server/central/config"
	"github.com/tidbcloud/pkgv2/bizerr"
	tigrpc "github.com/tidbcloud/tiinf/transport/tigrpc/client"
	"go.uber.org/zap"
)

var (
	accountProviderSvcOnce sync.Once
	accountProviderSvcCli  account.AccountAPIServiceClient
)

func getAccountSvcClient() account.AccountAPIServiceClient {
	accountProviderSvcOnce.Do(func() {

		logger, err := zap.NewProduction()
		if err != nil {
			log.Fatalf("failed to init zap logger")
		}
		defer logger.Sync()
		time.Sleep(time.Second * 5)

		conn, err := tigrpc.NewClientConn(config.Global().GrpcConfig.AccountProviderSvcAddr, tigrpc.WithDefault(), tigrpc.WithZapLogger(logger))
		if err != nil {
			panic(fmt.Sprintf("dial account-svc: %s", err))
		}

		accountProviderSvcCli = account.NewAccountAPIServiceClient(conn)
	})

	return accountProviderSvcCli
}

func GetUserByEmail(ctx context.Context, req *account.GetUserByEmailRequest) (*account.GetUserByEmailResponse, bizerr.BizError) {
	client := getAccountSvcClient()

	resp, err := client.GetUserByEmail(ctx, req)
	if err != nil {
		return resp, bizerr.WrapGrpcError(err, "GetUserByEmail")
	}
	if resp.BaseResp.ErrCode != 0 {
		return resp, bizerr.Restore(bizerr.ErrCode(resp.BaseResp.ErrCode), resp.BaseResp.ErrMsg)
	}

	return resp, nil
}

func GetAuthUser(ctx context.Context, req *account.GetAuthUserRequest) (*account.GetAuthUserResponse, bizerr.BizError) {
	client := getAccountSvcClient()

	resp, err := client.GetAuthUser(ctx, req)
	if err != nil {
		return resp, bizerr.WrapGrpcError(err, "GetAuthUser")
	}
	if resp.BaseResp.ErrCode != 0 {
		return resp, bizerr.Restore(bizerr.ErrCode(resp.BaseResp.ErrCode), resp.BaseResp.ErrMsg)
	}
	return resp, nil
}

func GetUserByID(ctx context.Context, req *account.GetUserByIDRequest) (*account.GetUserByIDResponse, bizerr.BizError) {
	client := getAccountSvcClient()

	resp, err := client.GetUserByID(ctx, req)
	if err != nil {
		return resp, bizerr.WrapGrpcError(err, "GetUserByID")
	}
	if resp.BaseResp.ErrCode != 0 {
		return resp, bizerr.Restore(bizerr.ErrCode(resp.BaseResp.ErrCode), resp.BaseResp.ErrMsg)
	}
	return resp, nil
}

func GetProjectByID(ctx context.Context, req *account.GetProjectByIDRequest) (*account.GetProjectByIDResponse, bizerr.BizError) {
	client := getAccountSvcClient()

	resp, err := client.GetProjectByID(ctx, req)
	if err != nil {
		return resp, bizerr.WrapGrpcError(err, "GetProjectByID")
	}
	if resp.BaseResp.ErrCode != 0 {
		return resp, bizerr.Restore(bizerr.ErrCode(resp.BaseResp.ErrCode), resp.BaseResp.ErrMsg)
	}
	return resp, nil
}

func CreateAuditLog(ctx context.Context, req *account.CreateAuditLogRequest) (*account.CreateAuditLogResponse, bizerr.BizError) {
	client := getAccountSvcClient()

	resp, err := client.CreateAuditLog(ctx, req)
	if err != nil {
		return resp, bizerr.WrapGrpcError(err, "CreateAuditLog")
	}
	if resp.BaseResp.ErrCode != 0 {
		return resp, bizerr.Restore(bizerr.ErrCode(resp.BaseResp.ErrCode), resp.BaseResp.ErrMsg)
	}
	return resp, nil
}
