package v4a

import (
	
	
	
	

	awsmiddleware 
	v4 
	
	
	smithyHTTP 
)

// HTTPPresigner is an interface to a SigV4a signer that can sign create a
// presigned URL for a HTTP requests.
type HTTPPresigner interface {
	PresignHTTP(
		ctx context.Context, credentials Credentials, r *http.Request,
		payloadHash string, service string, regionSet []string, signingTime time.Time,
		optFns ...func(*SignerOptions),
	) (url string, signedHeader http.Header, err error)
}

// PresignHTTPRequestMiddlewareOptions is the options for the PresignHTTPRequestMiddleware middleware.
type PresignHTTPRequestMiddlewareOptions struct {
	CredentialsProvider CredentialsProvider
	Presigner           HTTPPresigner
	LogSigning          bool
}

// PresignHTTPRequestMiddleware provides the Finalize middleware for creating a
// presigned URL for an HTTP request.
//
// Will short circuit the middleware stack and not forward onto the next
// Finalize handler.
type PresignHTTPRequestMiddleware struct {
	credentialsProvider CredentialsProvider
	presigner           HTTPPresigner
	logSigning          bool
}

// NewPresignHTTPRequestMiddleware returns a new PresignHTTPRequestMiddleware
// initialized with the presigner.
func ( PresignHTTPRequestMiddlewareOptions) *PresignHTTPRequestMiddleware {
	return &PresignHTTPRequestMiddleware{
		credentialsProvider: .CredentialsProvider,
		presigner:           .Presigner,
		logSigning:          .LogSigning,
	}
}

// ID provides the middleware ID.
func (*PresignHTTPRequestMiddleware) () string { return "PresignHTTPRequest" }

// HandleFinalize will take the provided input and create a presigned url for
// the http request using the SigV4 presign authentication scheme.
func ( *PresignHTTPRequestMiddleware) (
	 context.Context,  middleware.FinalizeInput,  middleware.FinalizeHandler,
) (
	 middleware.FinalizeOutput,  middleware.Metadata,  error,
) {
	,  := .Request.(*smithyHTTP.Request)
	if ! {
		return , , &SigningError{
			Err: fmt.Errorf("unexpected request middleware type %T", .Request),
		}
	}

	 := .Build()
	if !hasCredentialProvider(.credentialsProvider) {
		.Result = &v4.PresignedHTTPRequest{
			URL:          .URL.String(),
			Method:       .Method,
			SignedHeader: http.Header{},
		}

		return , , nil
	}

	 := awsmiddleware.GetSigningName()
	 := awsmiddleware.GetSigningRegion()
	 := v4.GetPayloadHash()
	if len() == 0 {
		return , , &SigningError{
			Err: fmt.Errorf("computed payload hash missing from context"),
		}
	}

	,  := .credentialsProvider.RetrievePrivateKey()
	if  != nil {
		return , , &SigningError{
			Err: fmt.Errorf("failed to retrieve credentials: %w", ),
		}
	}

	, ,  := .presigner.PresignHTTP(, ,
		, , , []string{}, sdk.NowTime(),
		func( *SignerOptions) {
			.Logger = middleware.GetLogger()
			.LogSigning = .logSigning
		})
	if  != nil {
		return , , &SigningError{
			Err: fmt.Errorf("failed to sign http request, %w", ),
		}
	}

	.Result = &v4.PresignedHTTPRequest{
		URL:          ,
		Method:       .Method,
		SignedHeader: ,
	}

	return , , nil
}