package aws

import (
	"bytes"

	"net/http"
	"path"

	"bitbucket.org/nemt/nemt-portal-api/infra/config"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
	"github.com/aws/aws-sdk-go/service/ssm"
)

//AWSUtil return the methods to interact with AWS Services
type AWSUtil struct {
	configApp  *config.Config
	awsConfig  *aws.Config
	s3Service  *s3.S3
	ssmService *ssm.SSM
	awsSession *session.Session
}

//New return an instance of AWSUtil
func New(configApp *config.Config) *AWSUtil {
	cfg := aws.NewConfig().WithRegion("sa-east-1")
	cfg.DisableRestProtocolURICleaning = aws.Bool(true)

	return &AWSUtil{
		configApp:  configApp,
		awsConfig:  cfg,
		s3Service:  s3.New(session.New(), cfg),
		ssmService: ssm.New(session.New(), cfg),
		awsSession: session.New(cfg),
	}
}

//DownloadFromS3Bucket will return the file on the S3 Bucket
func (a AWSUtil) DownloadFromS3Bucket(filePath string) ([]byte, error) {
	downloader := s3manager.NewDownloader(a.awsSession)

	b := &aws.WriteAtBuffer{}
	_, err := downloader.Download(b, &s3.GetObjectInput{
		Bucket: aws.String(a.configApp.Aws.S3Bucket),
		Key:    aws.String(filePath),
	})

	if err != nil {
		return []byte{}, err
	} else {
		return b.Bytes(), nil
	}
}

//UploadToS3Bucket will upload a file to the S3 Bucket
func (a AWSUtil) UploadToS3Bucket(filePath string, fileName string, buff []byte) error {
	fileBytes := bytes.NewReader(buff)
	fileType := http.DetectContentType(buff)

	fullPath := path.Join(filePath, fileName)

	params := &s3.PutObjectInput{
		Bucket:        aws.String(a.configApp.Aws.S3Bucket),
		Key:           aws.String(fullPath),
		Body:          fileBytes,
		ContentLength: aws.Int64(int64(len(buff))),
		ContentType:   aws.String(fileType),
	}

	_, err := a.s3Service.PutObject(params)
	if err != nil {
		return err
	}

	return nil
}

//SsmPutParameter put parameter to SSM
func (a AWSUtil) SsmPutParameter(parameterName string, parameterValue string) error {
	params := &ssm.PutParameterInput{
		Name:  aws.String(parameterName),
		Type:  aws.String("SecureString"),
		Value: aws.String(parameterValue),
	}

	_, err := a.ssmService.PutParameter(params)
	if err != nil {
		return err
	}

	return nil
}

//SsmGetParameter get parameter from SSM
func (a AWSUtil) SsmGetParameter(parameterName string, withDecryption bool) (string, error) {
	params := &ssm.GetParameterInput{
		Name:           aws.String(parameterName),
		WithDecryption: aws.Bool(withDecryption),
	}

	output, err := a.ssmService.GetParameter(params)
	if err != nil {
		return "", err
	}

	return (*output.Parameter.Value), nil
}
