You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: pkce_auth.go
    path of file: ./repos/netbird/client/internal
    
    the code of the file until where you have to start completion: package internal

import (
	"context"
	"fmt"
	"net/url"

	log "github.com/sirupsen/logrus"
	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	mgm "github.com/netbirdio/netbird/management/client"
)

// PKCEAuthorizationFlow represents PKCE Authorization Flow information
type PKCEAuthorizationFlow struct {
	ProviderConfig PKCEAuthProviderConfig
}

// PKCEAuthProviderConfig has all attributes needed to initiate pkce authorization flow
type PKCEAuthProviderConfig struct {
	// ClientID An IDP application client id
	ClientID string
	// ClientSecret An IDP application client secret
	ClientSecret string
	// Audience An Audience for to authorization validation
	Audience string
	// TokenEndpoint is the endpoint of an IDP manager where clients can obtain access token
	TokenEndpoint string
	// AuthorizationEndpoint is the endpoint of an IDP manager where clients can obtain authorization code
	AuthorizationEndpoint string
	// Scopes provides the scopes to be included in the token request
	Scope string
	// RedirectURL handles authorization code from IDP manager
	RedirectURLs []string
	// UseIDToken indicates if the id token should be used for authentication
	UseIDToken bool
}

// GetPKCEAuthorizationFlowInfo initialize a PKCEAuthorizationFlow instance and return with it
func GetPKCEAuthorizationFlowInfo(ctx context.Context, privateKey string, mgmURL *url.URL) (PKCEAuthorizationFlow, error) {
	// validate our peer's Wireguard PRIVATE key
	myPrivateKey, err := wgtypes.ParseKey(privateKey)
	if err != nil {
		log.Errorf("failed parsing Wireguard key %s: [%s]", privateKey, err.Error())
		return PKCEAuthorizationFlow{}, err
	}

	var mgmTLSEnabled bool
	if mgmURL.Scheme == "https" {
		mgmTLSEnabled = true
	}

	log.Debugf("connecting to Management Service %s", mgmURL.String())
	mgmClient, err := mgm.NewClient(ctx, mgmURL.Host, myPrivateKey, mgmTLSEnabled)
	if err != nil {
		log.Errorf("failed connecting to Management Service %s %v", mgmURL.String(), err)
		return PKCEAuthorizationFlow{}, err
	}
	log.Debugf("connected to the Management service %s", mgmURL.String())

	defer func() {
		err = mgmClient.Close()
		if err != nil {
			log.Warnf("failed to close the Management service client %v", err)
		}
	}()

	serverKey, err := mgmClient.GetServerPublicKey()
	if err != nil {
		log.Errorf("failed while getting Management Service public key: %v", err)
		return PKCEAu
    
func GetPKCEAuthorizationFlowInfo(ctx context.Context, privateKey string, mgmURL *url.URL) (PKCEAuthorizationFlow, error) {
	// validate our peer's Wireguard PRIVATE key
	myPrivateKey, err := wgtypes.ParseKey(privateKey)
	if err != nil {
		log.Errorf("failed parsing Wireguard key %s: [%s]", privateKey, err.Error())
		return PKCEAuthorizationFlow{}, err
	}

	var mgmTLSEnabled bool
	if mgmURL.Scheme == "https" {
		mgmTLSEnabled = true
	}

	log.Debugf("connecting to Management Service %s", mgmURL.String())
	mgmClient, err := mgm.NewClient(ctx, mgmURL.Host, myPrivateKey, mgmTLSEnabled)
	if err != nil {
		log.Errorf("failed connecting to Management Service %s %v", mgmURL.String(), err)
		return PKCEAuthorizationFlow{}, err
	}
	log.Debugf("connected to the Management service %s", mgmURL.String())

	defer func() {
		err = mgmClient.Close()
		if err != nil {
			log.Warnf("failed to close the Management service client %v", err)
		}
	}()

	serverKey, err := mgmClient.GetServerPublicKey()
	if err != nil {
		log.Errorf("failed while getting Management Service public key: %v", err)
		return PKCEAuthorizationFlow{}, err
	}

	protoPKCEAuthorizationFlow, err := mgmClient.GetPKCEAuthorizationFlow(*serverKey)
	if err != nil {
		if s, ok := status.FromError(err); ok && s.Code() == codes.NotFound {
			log.Warnf("server couldn't find pkce flow, contact admin: %v", err)
			return PKCEAuthorizationFlow{}, err
		}
		log.Errorf("failed to retrieve pkce flow: %v", err)
		return PKCEAuthorizationFlow{}, err
	}

	authFlow := PKCEAuthorizationFlow{
		ProviderConfig: PKCEAuthProviderConfig{
			Audience:              protoPKCEAuthorizationFlow.GetProviderConfig().GetAudience(),
			ClientID:              protoPKCEAuthorizationFlow.GetProviderConfig().GetClientID(),
			ClientSecret:          protoPKCEAuthorizationFlow.GetProviderConfig().GetClientSecret(),
			TokenEndpoint:         protoPKCEAuthorizationFlow.GetProviderConfig().GetTokenEndpoint(),
			AuthorizationEndpoint: protoPKCEAuthorizationFlow.GetProviderConfig().GetAuthorizationEndpoint(),
			Scope:                 protoPKCEAuthorizationFlow.GetProviderConfig().GetScope(),
			RedirectURLs:          protoPKCEAuthorizationFlow.GetProviderConfig().GetRedirectURLs(),
			UseIDToken:            protoPKCEAuthorizationFlow.GetProviderConfig().GetUseIDToken(),
		},
	}

	err = isPKCEProviderConfigValid(authFlow.ProviderConfig)
	if err != nil {
		return PKCEAuthorizationFlow{}, err
	}

	return authFlow, nil
}