package middlewares

import (
	"fmt"
	"strings"

	"github.com/snyk/driftctl/pkg/resource"
	"github.com/snyk/driftctl/pkg/resource/google"
)

// GoogleIAMBindingTransformer Transforms Bucket IAM binding in bucket iam member to ease comparison.
type GoogleIAMBindingTransformer struct {
	resourceFactory resource.ResourceFactory
	resFieldByType  map[string]string // map of the field to add to resource attribute for all supported type
}

func NewGoogleIAMBindingTransformer(resourceFactory resource.ResourceFactory) *GoogleIAMBindingTransformer {
	return &GoogleIAMBindingTransformer{
		resourceFactory,
		map[string]string{
			google.GoogleStorageBucketIamBindingResourceType: "bucket",
			google.GoogleProjectIamBindingResourceType:       "project",
		},
	}
}

func (m *GoogleIAMBindingTransformer) Execute(_, resourcesFromState *[]*resource.Resource) error {

	resources := make([]*resource.Resource, 0)

	for _, stateRes := range *resourcesFromState {
		// Ignore all resources other than IamBinding
		resType := stateRes.ResourceType()
		resField, supported := m.resFieldByType[resType]
		if !supported {
			resources = append(resources, stateRes)
			continue
		}

		resName := *stateRes.Attrs.GetString(resField)
		roleName := *stateRes.Attrs.GetString("role")
		members, _ := stateRes.Attrs.Get("members")

		for _, member := range members.([]interface{}) {
			id := fmt.Sprintf("%s/%s/%s", resName, roleName, member)
			resources = append(
				resources,
				m.resourceFactory.CreateAbstractResource(
					fmt.Sprintf("%s_member", strings.TrimSuffix(resType, "_binding")),
					id,
					map[string]interface{}{
						"id":     id,
						resField: resName,
						"role":   roleName,
						"member": member.(string),
					},
				),
			)
		}
	}

	*resourcesFromState = resources

	return nil
}
