package types

import (
	"fmt"
	"strconv"
	"strings"

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

type AliCloudRoleArn struct {
	AccountId string
	RoleType  string
	Role      string
}

const ALICLOUD_ROLE_ARN_PREFIX = "acs:ram::"

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

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

func (arn *AliCloudRoleArn) 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 := StringToAliCloudRoleArn(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: acs:ram::5841052134823325:role/auto-deploy-cli
func StringToAliCloudRoleArn(arn string) (*AliCloudRoleArn, error) {
	if !strings.HasPrefix(arn, ALICLOUD_ROLE_ARN_PREFIX) {
		return nil, errors.NotValidf("Invalid role arn prefix: %s", arn)
	}
	parts1 := strings.Split(arn[len(ALICLOUD_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 &AliCloudRoleArn{
		AccountId: parts1[0],
		RoleType:  parts2[0],
		Role:      parts2[1],
	}, nil
}
