package registration

import (
	"errors"
	"strings"
	"time"

	"code.justin.tv/sse/malachai/pkg/registration/iamgenerator"
)

// Service represents an s2s service
type Service struct {
	ID                       string    `dynamodbav:"service_id"`
	Name                     string    `dynamodbav:"service_name"`
	OwnerLDAPGroups          []string  `dynamodbav:"owner_ldap_groups"`
	RoleArn                  string    `dynamodbav:"role_arn"`
	ServicesReadOnlyRoleName string    `dynamodbav:"ro_role_shard_name"`
	AllowedArns              []string  `dynamodbav:"allowed_arns"`
	CapabilitiesTopicArn     string    `dynamodbav:"capabilities_topic_arn"`
	LastUpdatedByUser        string    `dynamodbav:"last_updated_by_user"`
	Private                  bool      `dynamodbav:"private"`
	SandstormRoleArn         string    `dynamodbav:"sandstorm_role_arn"`
	SandstormRoleName        string    `dynamodbav:"sandstorm_role_name"`
	SandstormSecretName      string    `dynamodbav:"sandstorm_secret_name"`
	CreatedAt                time.Time `dynamodbav:"created_at,unixtime"`
	UpdatedAt                time.Time `dynamodbav:"updated_at,unixtime"`

	// TODO this will be removed
	CallerRoleArn string `dynamodbav:"caller_role_arn"`
	CalleeRoleArn string `dynamodbav:"callee_role_arn"`

	iam iamgenerator.IAMGenerator
}

func (s *Service) forIAMGenerator() *iamgenerator.Service {
	return &iamgenerator.Service{
		ID:                       s.ID,
		Name:                     s.Name,
		RoleArn:                  s.RoleArn,
		ServicesReadOnlyRoleName: s.ServicesReadOnlyRoleName,
		AllowedArns:              s.AllowedArns,
		CapabilitiesTopicArn:     s.CapabilitiesTopicArn,
		LastUpdatedByUser:        s.LastUpdatedByUser,
		Private:                  s.Private,
		SandstormRoleArn:         s.SandstormRoleArn,
		SandstormRoleName:        s.SandstormRoleName,
		SandstormSecretName:      s.SandstormSecretName,
		CreatedAt:                s.CreatedAt,
		UpdatedAt:                s.UpdatedAt,
	}
}

var errInvalidARN = errors.New("not a valid arn")

// arn:aws:iam::196915980276:role/admin-panel-canary
func parseAccountIDFromArn(arn string) (accountID string, err error) {
	parts := strings.Split(arn, ":")
	if len(parts) != 6 {
		return "", errInvalidARN
	}
	accountID = parts[4]
	if accountID == "" {
		return "", errInvalidARN
	}
	return parts[4], nil
}

func (s *Service) allowedAccountIDs() ([]string, error) {
	uniqueIDs := map[string]struct{}{}
	for _, allowedArn := range s.AllowedArns {
		accountID, err := parseAccountIDFromArn(allowedArn)
		if err != nil {
			return nil, err
		}
		uniqueIDs[accountID] = struct{}{}
	}
	accountIDs := make([]string, 0, len(uniqueIDs))
	for k := range uniqueIDs {
		accountIDs = append(accountIDs, k)
	}
	return accountIDs, nil
}

func (s *Service) getCapabilitiesTopic() (topic string) {
	return "CAPABILITIES-" + s.ID
}

// GetValidAllowedARNs returns all allowed arns that can be validated.
// This will weekd out any arns that have been deleted.
func (s *Service) GetValidAllowedARNs() ([]string, error) {
	return s.iam.GetValidAllowedARNs(s.ID, s.AllowedArns)
}
