package validation

import (
	"context"
	"fmt"
	"strconv"

	awsArn "github.com/aws/aws-sdk-go/aws/arn"

	"code.justin.tv/eventbus/controlplane/internal/arn"

	"code.justin.tv/eventbus/controlplane/internal/db"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/pkg/errors"
)

type IAMRole struct {
	*db.IAMRole
	EncryptionAtRestGrantFetcher GrantFetcher
}

func (i *IAMRole) ID() string {
	return itemID(i)
}

func (i *IAMRole) Type() string {
	return "IAMRole"
}

func (i *IAMRole) Attributes() []*ItemAttribute {
	return []*ItemAttribute{
		{
			Key:   "ID",
			Value: strconv.Itoa(i.IAMRole.ID),
		},
		{
			Key:   "ServiceID",
			Value: strconv.Itoa(i.IAMRole.ServiceID),
		},
		{
			Key:   "IAMRole",
			Value: i.ARN,
		},
		{
			Key:   "Label",
			Value: i.Label,
		},
	}
}

func (i *IAMRole) Validate(ctx context.Context) (*Report, error) {
	parsedARN, err := awsArn.Parse(i.ARN)
	if err != nil {
		return nil, errors.Wrap(err, "could not parse IAM role ARN")
	}
	rootARN := arn.IAMRootARN(parsedARN.AccountID)

	grant, err := i.EncryptionAtRestGrantFetcher.FindByGrantID(ctx, i.KMSGrantID)
	if err != nil {
		return nil, errors.Wrap(err, "could not fetch encryption at rest grants")
	} else if grant == nil {
		return Warn(i, "Encryption-at-rest permissions not found"), nil
	}

	granteePrincipal := aws.StringValue(grant.GranteePrincipal)
	if granteePrincipal != rootARN {
		msg := fmt.Sprintf("Expecting encryption-at-rest permissions granted to '%s', found '%s'", rootARN, granteePrincipal)
		return Warn(i, msg), nil
	}

	return Ok(i), nil
}
