package types

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/juju/errors"
	"gopkg.in/yaml.v3"
)

type AwsRoleArn struct {
	AccountId string
	RoleType  string
	Role      string
}

const ROLE_ARN_PREFIX = "arn:aws:iam::"

func (arn *AwsRoleArn) String() string {
	return fmt.Sprintf("%s%s:%s/%s", ROLE_ARN_PREFIX, arn.AccountId, arn.RoleType, arn.Role)
}

func (arn *AwsRoleArn) MarshalYAML() (interface{}, error) {
	return arn.String(), nil
}

func (arn *AwsRoleArn) UnmarshalYAML(value *yaml.Node) error {
	if value.Kind != yaml.ScalarNode || value.ShortTag() != "!!str" {
		return errors.Errorf("Invalid node tag %s", string(value.Tag))
	}

	newArn, err := FromRoleArnString(value.Value)
	if err != nil {
		return errors.Annotatef(err, "Failed to parse aws role arn: %s", string(value.Value))
	}
	*arn = *newArn
	return nil
}

// Parse role arn from string
// arn is like: arn:aws:iam::385595570414:role/eksctl-dev-us-west-eric2
func FromRoleArnString(arn string) (*AwsRoleArn, error) {
	if !strings.HasPrefix(arn, ROLE_ARN_PREFIX) {
		return nil, errors.NotValidf("Invalid role arn prefix: %s", arn)
	}
	parts1 := strings.Split(arn[len(ROLE_ARN_PREFIX):], ":")
	if len(parts1) != 2 {
		return nil, errors.NotValidf("Invalid role arn format: %s", arn)
	}
	if _, err := strconv.Atoi(parts1[0]); err != nil {
		return nil, errors.NotValidf("Invalid role arn account id: %s", arn)
	}
	parts2 := strings.SplitN(parts1[1], "/", 2)
	if len(parts2) != 2 {
		return nil, errors.NotValidf("Invalid role arn: %s", arn)
	}
	return &AwsRoleArn{
		AccountId: parts1[0],
		RoleType:  parts2[0],
		Role:      parts2[1],
	}, nil
}
