// Code generated by protoc-gen-slimrpc-go. DO NOT EDIT.
// source: example_with_imports.proto

package types

import (
	"context"
	"fmt"
	"time"

	slim_bindings "github.com/agntcy/slim-bindings-go"
	"github.com/agntcy/slim-bindings-go/slimrpc"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/emptypb"
	a2a_a2apb "github.com/a2aproject/a2a-go/a2apb"
)


// TestClient is the client API for Test service.
type TestClient interface {
	ExampleUnaryUnary(ctx context.Context, req *a2a_a2apb.ExampleRequest) (*a2a_a2apb.ExampleResponse, error)
	ExampleUnaryStream(ctx context.Context, req *a2a_a2apb.ExampleRequest) (slimrpc.ResponseStream[*a2a_a2apb.ExampleResponse], error)
	ExampleStreamUnary(ctx context.Context) (slimrpc.ClientRequestStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse], error)
	ExampleStreamStream(ctx context.Context) (slimrpc.ClientBidiStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse], error)
	Delete(ctx context.Context, req *a2a_a2apb.DeleteRequest) (*emptypb.Empty, error)
}

type TestClientImpl struct {
	channel *slim_bindings.Channel
}

// NewTestClient creates a new Test client.
func NewTestClient(channel *slim_bindings.Channel) TestClient {
	return &TestClientImpl{
		channel: channel,
	}
}


func (c *TestClientImpl) ExampleUnaryUnary(ctx context.Context, req *a2a_a2apb.ExampleRequest) (*a2a_a2apb.ExampleResponse, error) {
	// Serialize request
	reqBytes, err := proto.Marshal(req)
	if err != nil {
		return nil, err
	}

	// Extract timeout from context
	var timeout *time.Duration
	if deadline, ok := ctx.Deadline(); ok {
		t := time.Until(deadline)
		timeout = &t
	}

	// Extract metadata from context
	var metadata *map[string]string
	if md, ok := slimrpc.MetadataFromContext(ctx); ok {
		metadata = &md
	}

	// Make RPC call
	respBytes, err := c.channel.CallUnaryAsync("example_service.Test", "ExampleUnaryUnary", reqBytes, timeout, metadata)
	if err != nil {
		return nil, err
	}

	// Deserialize response
	resp := &a2a_a2apb.ExampleResponse{}
	if err := proto.Unmarshal(respBytes, resp); err != nil {
		return nil, err
	}

	return resp, nil
}

func (c *TestClientImpl) ExampleUnaryStream(ctx context.Context, req *a2a_a2apb.ExampleRequest) (slimrpc.ResponseStream[*a2a_a2apb.ExampleResponse], error) {
	// Serialize request
	reqBytes, err := proto.Marshal(req)
	if err != nil {
		return nil, err
	}

	// Extract timeout from context
	var timeout *time.Duration
	if deadline, ok := ctx.Deadline(); ok {
		t := time.Until(deadline)
		timeout = &t
	}

	// Extract metadata from context
	var metadata *map[string]string
	if md, ok := slimrpc.MetadataFromContext(ctx); ok {
		metadata = &md
	}

	// Make RPC call
	stream, err := c.channel.CallUnaryStreamAsync("example_service.Test", "ExampleUnaryStream", reqBytes, timeout, metadata)
	if err != nil {
		return nil, err
	}

	return slimrpc.NewClientResponseStream[*a2a_a2apb.ExampleResponse](stream), nil
}

func (c *TestClientImpl) ExampleStreamUnary(ctx context.Context) (slimrpc.ClientRequestStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse], error) {
	// Extract timeout from context
	var timeout *time.Duration
	if deadline, ok := ctx.Deadline(); ok {
		t := time.Until(deadline)
		timeout = &t
	}

	// Extract metadata from context
	var metadata *map[string]string
	if md, ok := slimrpc.MetadataFromContext(ctx); ok {
		metadata = &md
	}

	stream := c.channel.CallStreamUnary("example_service.Test", "ExampleStreamUnary", timeout, metadata)
	return slimrpc.NewClientRequestStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse](stream), nil
}

func (c *TestClientImpl) ExampleStreamStream(ctx context.Context) (slimrpc.ClientBidiStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse], error) {
	// Extract timeout from context
	var timeout *time.Duration
	if deadline, ok := ctx.Deadline(); ok {
		t := time.Until(deadline)
		timeout = &t
	}

	// Extract metadata from context
	var metadata *map[string]string
	if md, ok := slimrpc.MetadataFromContext(ctx); ok {
		metadata = &md
	}

	stream := c.channel.CallStreamStream("example_service.Test", "ExampleStreamStream", timeout, metadata)
	return slimrpc.NewClientBidiStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse](stream), nil
}

func (c *TestClientImpl) Delete(ctx context.Context, req *a2a_a2apb.DeleteRequest) (*emptypb.Empty, error) {
	// Serialize request
	reqBytes, err := proto.Marshal(req)
	if err != nil {
		return nil, err
	}

	// Extract timeout from context
	var timeout *time.Duration
	if deadline, ok := ctx.Deadline(); ok {
		t := time.Until(deadline)
		timeout = &t
	}

	// Extract metadata from context
	var metadata *map[string]string
	if md, ok := slimrpc.MetadataFromContext(ctx); ok {
		metadata = &md
	}

	// Make RPC call
	respBytes, err := c.channel.CallUnaryAsync("example_service.Test", "Delete", reqBytes, timeout, metadata)
	if err != nil {
		return nil, err
	}

	// Deserialize response
	resp := &emptypb.Empty{}
	if err := proto.Unmarshal(respBytes, resp); err != nil {
		return nil, err
	}

	return resp, nil
}


// TestServer is the server API for Test service.
// All implementations must embed UnimplementedTestServer
// for forward compatibility
type TestServer interface {
	ExampleUnaryUnary(ctx context.Context, req *a2a_a2apb.ExampleRequest) (*a2a_a2apb.ExampleResponse, error)
	ExampleUnaryStream(ctx context.Context, req *a2a_a2apb.ExampleRequest, stream slimrpc.RequestStream[*a2a_a2apb.ExampleResponse]) error
	ExampleStreamUnary(ctx context.Context, stream slimrpc.ResponseStream[*a2a_a2apb.ExampleRequest]) (*a2a_a2apb.ExampleResponse, error)
	ExampleStreamStream(ctx context.Context, stream slimrpc.ServerBidiStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse]) error
	Delete(ctx context.Context, req *a2a_a2apb.DeleteRequest) (*emptypb.Empty, error)
}

// UnimplementedTestServer must be embedded to have forward compatible implementations.
type UnimplementedTestServer struct {
}


func (UnimplementedTestServer) ExampleUnaryUnary(ctx context.Context, req *a2a_a2apb.ExampleRequest) (*a2a_a2apb.ExampleResponse, error) {
	return nil, fmt.Errorf("method ExampleUnaryUnary not implemented")
}

func (UnimplementedTestServer) ExampleUnaryStream(ctx context.Context, req *a2a_a2apb.ExampleRequest, stream slimrpc.RequestStream[*a2a_a2apb.ExampleResponse]) error {
	return fmt.Errorf("method ExampleUnaryStream not implemented")
}

func (UnimplementedTestServer) ExampleStreamUnary(ctx context.Context, stream slimrpc.ResponseStream[*a2a_a2apb.ExampleRequest]) (*a2a_a2apb.ExampleResponse, error) {
	return nil, fmt.Errorf("method ExampleStreamUnary not implemented")
}

func (UnimplementedTestServer) ExampleStreamStream(ctx context.Context, stream slimrpc.ServerBidiStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse]) error {
	return fmt.Errorf("method ExampleStreamStream not implemented")
}

func (UnimplementedTestServer) Delete(ctx context.Context, req *a2a_a2apb.DeleteRequest) (*emptypb.Empty, error) {
	return nil, fmt.Errorf("method Delete not implemented")
}


// RegisterTestServer registers the server with slim_bindings.
func RegisterTestServer(server *slim_bindings.Server, impl TestServer) {
	server.RegisterUnaryUnary("example_service.Test", "ExampleUnaryUnary", &Test_ExampleUnaryUnary_Handler{impl: impl})
	server.RegisterUnaryStream("example_service.Test", "ExampleUnaryStream", &Test_ExampleUnaryStream_Handler{impl: impl})
	server.RegisterStreamUnary("example_service.Test", "ExampleStreamUnary", &Test_ExampleStreamUnary_Handler{impl: impl})
	server.RegisterStreamStream("example_service.Test", "ExampleStreamStream", &Test_ExampleStreamStream_Handler{impl: impl})
	server.RegisterUnaryUnary("example_service.Test", "Delete", &Test_Delete_Handler{impl: impl})
}


type Test_ExampleUnaryUnary_Handler struct {
	impl TestServer
}

func (h *Test_ExampleUnaryUnary_Handler) Handle(request []byte, rpcContext *slim_bindings.Context) ([]byte, error) {
	req := &a2a_a2apb.ExampleRequest{}
	if err := proto.Unmarshal(request, req); err != nil {
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInvalidArgument,
			err.Error(),
			nil,
		)
	}

	// Convert slim_bindings.Context to context.Context
	ctx, cancel := slimrpc.ContextFromRpcContext(rpcContext)
	defer cancel()

	resp, err := h.impl.ExampleUnaryUnary(ctx, req)
	if err != nil {
		// Check if it's already an RpcError
		if rpcErr, ok := err.(*slim_bindings.RpcError); ok {
			return nil, rpcErr
		}
		// Convert generic errors to RpcError
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
	}

	respBytes, err := proto.Marshal(resp)
	if err != nil {
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
	}
	return respBytes, nil
}

type Test_ExampleUnaryStream_Handler struct {
	impl TestServer
}

func (h *Test_ExampleUnaryStream_Handler) Handle(request []byte, rpcContext *slim_bindings.Context, sink *slim_bindings.ResponseSink) error {
	req := &a2a_a2apb.ExampleRequest{}
	if err := proto.Unmarshal(request, req); err != nil {
		rpcErr := slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInvalidArgument,
			err.Error(),
			nil,
		)
		sink.SendErrorAsync(rpcErr)
		return rpcErr
	}

	// Convert slim_bindings.Context to context.Context
	ctx, cancel := slimrpc.ContextFromRpcContext(rpcContext)
	defer cancel()

	stream := slimrpc.NewServerRequestStream[*a2a_a2apb.ExampleResponse](sink)
	err := h.impl.ExampleUnaryStream(ctx, req, stream)

	// Close the stream after handler returns
	closeErr := sink.CloseAsync()
	if err == nil {
		err = closeErr
	}

	if err != nil {
		// Check if it's already an RpcError
		if rpcErr, ok := err.(*slim_bindings.RpcError); ok {
			sink.SendErrorAsync(rpcErr)
			return rpcErr
		}
		// Convert generic errors to RpcError
		rpcErr := slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
		sink.SendErrorAsync(rpcErr)
		return rpcErr
	}

	return nil
}

type Test_ExampleStreamUnary_Handler struct {
	impl TestServer
}

func (h *Test_ExampleStreamUnary_Handler) Handle(stream *slim_bindings.RequestStream, rpcContext *slim_bindings.Context) ([]byte, error) {
	// Convert slim_bindings.Context to context.Context
	ctx, cancel := slimrpc.ContextFromRpcContext(rpcContext)
	defer cancel()

	responseStream := slimrpc.NewServerResponseStream[*a2a_a2apb.ExampleRequest](stream)

	resp, err := h.impl.ExampleStreamUnary(ctx, responseStream)
	if err != nil {
		if rpcErr, ok := err.(*slim_bindings.RpcError); ok {
			return nil, rpcErr
		}
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
	}

	respBytes, err := proto.Marshal(resp)
	if err != nil {
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
	}
	return respBytes, nil
}

type Test_ExampleStreamStream_Handler struct {
	impl TestServer
}

func (h *Test_ExampleStreamStream_Handler) Handle(stream *slim_bindings.RequestStream, rpcContext *slim_bindings.Context, sink *slim_bindings.ResponseSink) error {
	// Convert slim_bindings.Context to context.Context
	ctx, cancel := slimrpc.ContextFromRpcContext(rpcContext)
	defer cancel()

	serverStream := slimrpc.NewServerBidiStream[*a2a_a2apb.ExampleRequest, *a2a_a2apb.ExampleResponse](stream, sink)
	err := h.impl.ExampleStreamStream(ctx, serverStream)

	// Close the stream after handler returns
	closeErr := sink.CloseAsync()
	if err == nil {
		err = closeErr
	}

	if err != nil {
		// Check if it's already an RpcError
		if rpcErr, ok := err.(*slim_bindings.RpcError); ok {
			sink.SendErrorAsync(rpcErr)
			return rpcErr
		}
		// Convert generic errors to RpcError
		rpcErr := slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
		sink.SendErrorAsync(rpcErr)
		return rpcErr
	}

	return nil
}

type Test_Delete_Handler struct {
	impl TestServer
}

func (h *Test_Delete_Handler) Handle(request []byte, rpcContext *slim_bindings.Context) ([]byte, error) {
	req := &a2a_a2apb.DeleteRequest{}
	if err := proto.Unmarshal(request, req); err != nil {
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInvalidArgument,
			err.Error(),
			nil,
		)
	}

	// Convert slim_bindings.Context to context.Context
	ctx, cancel := slimrpc.ContextFromRpcContext(rpcContext)
	defer cancel()

	resp, err := h.impl.Delete(ctx, req)
	if err != nil {
		// Check if it's already an RpcError
		if rpcErr, ok := err.(*slim_bindings.RpcError); ok {
			return nil, rpcErr
		}
		// Convert generic errors to RpcError
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
	}

	respBytes, err := proto.Marshal(resp)
	if err != nil {
		return nil, slim_bindings.NewRpcErrorRpc(
			slim_bindings.RpcCodeInternal,
			err.Error(),
			nil,
		)
	}
	return respBytes, nil
}


