package grpcprocess

import (
	
	

	
	
	

	
)

// ClientConn is a process-managed gRPC client connection.
type ClientConn interface {
	grpc.ClientConnInterface
	process.Runner
}

// ClientFunc creates a gRPC client connection using the given context.
type ClientFunc func(context.Context) (*grpc.ClientConn, error)

// Client returns a [ClientConn] that creates its underlying [grpc.ClientConn]
// using connect at application runtime.
func ( ClientFunc) ClientConn {
	return &client{connect: }
}

type client struct {
	connect ClientFunc
	conn    atomic.Pointer[grpc.ClientConn]
}

// Run implements the [process.Runner] interface.
func ( *client) ( context.Context,  process.Callback) error {
	,  := .connect()
	if  != nil {
		return 
	}

	.conn.Store()

	 := ()

	.conn.CompareAndSwap(, nil)

	_ = .Close()

	return 
}

// Invoke implements [grpc.ClientConnInterface].
func ( *client) (
	 context.Context,
	 string,
	,  any,
	 ...grpc.CallOption,
) error {
	,  := .load()
	if  != nil {
		return 
	}
	return .Invoke(, , , , ...)
}

// NewStream implements [grpc.ClientConnInterface].
func ( *client) (
	 context.Context,
	 *grpc.StreamDesc,
	 string,
	 ...grpc.CallOption,
) (grpc.ClientStream, error) {
	,  := .load()
	if  != nil {
		return nil, 
	}
	return .NewStream(, , , ...)
}

func ( *client) () (*grpc.ClientConn, error) {
	 := .conn.Load()
	if  == nil {
		return nil, status.Error(
			codes.Canceled,
			"grpcprocess: client connection is not running",
		)
	}
	return , nil
}