package lambda

import (
	"context"
	"flag"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/lambda"
	"github.com/aws/aws-sdk-go/service/lambda/lambdaiface"
	"github.com/google/subcommands"
	"github.com/sirupsen/logrus"
)

// UpdateLambdaFuncCmd updates all ecs tasks
type UpdateLambdaFuncCmd struct {
	Logger logrus.FieldLogger

	environment string
	lambda      lambdaiface.LambdaAPI
	gitCommit   string
}

// Name implement subcommands
func (c *UpdateLambdaFuncCmd) Name() string {
	return "lambda"
}

// Synopsis implement subcommands
func (c *UpdateLambdaFuncCmd) Synopsis() string {
	return "update all the lambdas"
}

// Usage implement subcommands
func (c *UpdateLambdaFuncCmd) Usage() string {
	return `lambda -env <'staging', or 'prod'>
	`
}

// SetFlags implement subcommands
func (c *UpdateLambdaFuncCmd) SetFlags(f *flag.FlagSet) {
	f.StringVar(&c.environment, "env", "", "one of 'staging', or 'prod'")
	f.StringVar(&c.gitCommit, "git-commit", "", "git commit hash which need to be deployed to ecs")
}

//Execute implement subcommands
func (c *UpdateLambdaFuncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {

	if c.environment == "" {
		c.Logger.Error("ENVIRONMENT must be set")
		return subcommands.ExitFailure
	}

	err := c.execute()
	if err != nil {
		c.Logger.Error(err.Error())
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}

func (c *UpdateLambdaFuncCmd) execute() error {

	c.lambda = lambda.New(session.Must(session.NewSession(&aws.Config{
		Region: aws.String("us-west-2"),
	})))

	lambdas, err := getAllLambdaMetadata(c.environment, c.gitCommit)
	if err != nil {
		return err
	}

	for _, l := range lambdas {
		input := &lambda.UpdateFunctionCodeInput{
			FunctionName: aws.String(l.Name),
			S3Bucket:     aws.String(l.S3Bucket),
			S3Key:        aws.String(l.S3Key),
			Publish:      aws.Bool(true),
		}

		c.Logger.Infof("update function code for %s, using zip at s3://%s/%s", l.Name, l.S3Bucket, l.S3Key)
		_, err := c.lambda.UpdateFunctionCodeWithContext(context.Background(), input)
		if err != nil {
			return err
		}
	}
	return nil
}
