//go:build gofuzz
// +build gofuzz

package auth

import (
	"strings"
	"testing"
	"time"

	"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
	oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
	"github.com/aws/aws-sdk-go/aws/credentials"
	utils "github.com/trailofbits/go-fuzz-utils"
)

const (
	fuzzSuccessExitCode = 0
	fuzzFailExitCode    = -1
)

func InitFuzzAuthenticate() {
}

func DoFuzzAuthenticate(input []byte) int {
	// FUZZER INIT
	if len(input) < 100 {
		return fuzzFailExitCode
	}

	tp, err := utils.NewTypeProvider(input)
	if err != nil {
		return fuzzFailExitCode
	}

	var accessKeyAddr oid.Address
	err = tp.Fill(accessKeyAddr)
	if err != nil {
		return fuzzFailExitCode
	}

	accessKeyID := strings.ReplaceAll(accessKeyAddr.String(), "/", "0")
	secretKey, err := tp.GetString()
	awsCreds := credentials.NewStaticCredentials(accessKeyID, secretKey, "")

	reqData := RequestData{
		Method:   "GET",
		Endpoint: "http://localhost:8084",
		Bucket:   "my-bucket",
		Object:   "@obj/name",
	}
	presignData := PresignData{
		Service:  "s3",
		Region:   "spb",
		Lifetime: 10 * time.Minute,
		SignTime: time.Now().UTC(),
	}

	req, err := PresignRequest(awsCreds, reqData, presignData)
	if req == nil {
		return fuzzFailExitCode
	}

	expBox := &accessbox.Box{
		Gate: &accessbox.GateData{
			SecretKey: secretKey,
		},
	}

	mock := newTokensFrostfsMock()
	mock.addBox(accessKeyAddr, expBox)

	c := &Center{
		cli:     mock,
		reg:     NewRegexpMatcher(AuthorizationFieldRegexp),
		postReg: NewRegexpMatcher(postPolicyCredentialRegexp),
	}

	_, _ = c.Authenticate(req)

	return fuzzSuccessExitCode
}

func FuzzAuthenticate(f *testing.F) {
	f.Fuzz(func(t *testing.T, data []byte) {
		DoFuzzAuthenticate(data)
	})
}