package caller

import (
	"io"
	"net/http"

	"code.justin.tv/sse/malachai/pkg/log"
	"code.justin.tv/sse/malachai/pkg/s2s/internal"
)

// TwirpTransport ...
type TwirpTransport interface {
	Do(req *http.Request) (*http.Response, error)
}

// S2STwirpTransport returns a S2S wrapper twirp transport
//
// If logger is nil, it will be defaulted to a nil logger.
func S2STwirpTransport(
	callerName string,
	cfg *Config,
	inner TwirpTransport,
	logger log.S2SLogger,
) (TwirpTransport, error) {
	logger = log.NoOpIfNil(logger)

	signer, err := NewRequestSigner(callerName, cfg, logger)
	if err != nil {
		return nil, err
	}

	return &twirpTransport{
		inner:  inner,
		signer: signer,
	}, nil
}

type twirpTransport struct {
	inner  TwirpTransport
	signer RequestSignerAPI
}

// Do implements TwirpTransport
func (tt *twirpTransport) Do(req *http.Request) (*http.Response, error) {
	seeker, err := internal.WrapRequestBodyWithSeeker(req, 0)
	if err != nil {
		return nil, err
	}

	if err := tt.signer.SignRequest(req); err != nil {
		return nil, err
	}

	if _, err := seeker.Seek(0, io.SeekStart); err != nil {
		return nil, err
	}

	return tt.inner.Do(req)
}
