package policy

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"
)

// Delete deletes role
func (pg *IAMPolicyGenerator) Delete(roleName string, auth Authorizer) (err error) {
	// Validate input
	if roleName == "" {
		return InvalidInputError{prepend: "policy.Delete", msg: "roleName cannot be empty"}
	}

	owner, err := pg.GetRoleOwners(roleName)
	if err != nil {
		return err
	}

	// owner == nil when owner doesn't exist
	if owner != nil && auth != nil {
		err = auth.AuthorizeLDAPGroups(owner.LDAPGroups)
		if err != nil {
			return
		}
	}

	policyArn, doc, err := pg.GetAttachedRolePolicy(roleName)
	if err != nil {
		switch err.(type) {
		case InvalidRolePolicyError:
			err = nil
		case *InvalidRolePolicyError:
			err = nil
		default:
			pg.Logger.Errorf("policy: error retrieving role policy: %s", err.Error())
			return
		}

	}

	if policyArn != "" {

		// Authorize delete
		if auth != nil && owner == nil { // auth can be nil if Delete is being used in non-apiserver context

			err = auth.AuthorizeSecretKeys(ExtractPolicySecretKeys(doc))
			if err != nil {
				return
			}

		}

		_, err = pg.IAM.DetachRolePolicy(&iam.DetachRolePolicyInput{
			PolicyArn: aws.String(policyArn),
			RoleName:  aws.String(roleName),
		})
		if err != nil {
			pg.Logger.Errorf("policy: error detaching role policy: %s", err.Error())
			return
		}

		//Delete all the policy version except default version.
		err = pg.DeleteAllPolicyVersions(policyArn)
		if err != nil {
			pg.Logger.Errorf("Policy: error deleting role policy: %s", err.Error())
		}

		_, err = pg.IAM.DeletePolicy(&iam.DeletePolicyInput{PolicyArn: aws.String(policyArn)})
		if err != nil {
			if awsErr, ok := err.(awserr.RequestFailure); ok && awsErr.Message() == "Cannot delete a policy attached to entities." {

				// ignore error and continue
				err = nil

			} else {
				pg.Logger.Errorf("policy: error deleting role policy: %s", err.Error())
				return
			}
		}
	}

	var auxPolicyArn *string
	auxPolicyArn, err = pg.GetAttachedRoleAuxPolicyArn(roleName)
	if err != nil {
		pg.Logger.Errorf("policy: error getting aux policy for role %s: %s", roleName, err.Error())
		return
	}

	if auxPolicyArn != nil {
		_, err = pg.IAM.DetachRolePolicy(&iam.DetachRolePolicyInput{
			PolicyArn: aws.String(*auxPolicyArn),
			RoleName:  aws.String(roleName),
		})
		if err != nil {
			pg.Logger.Errorf("policy: error deleting aux policy %s: %s", *auxPolicyArn, err.Error())
			return
		}
	}

	_, err = pg.IAM.DeleteRole(&iam.DeleteRoleInput{RoleName: aws.String(roleName)})

	if err != nil {
		pg.Logger.Errorf("policy: error deleting role %s: %s", roleName, err.Error())
		return
	}

	// Only delete RoleOwner if group doesn't exist
	var groupName = roleName

	if owner != nil && !pg.CheckGroupExistence(groupName) {
		err = pg.DeleteRoleOwners(roleName, auth)
		if err != nil {
			return
		}
	}
	return
}
