package utils

import (
	"bytes"
	"io"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"go.uber.org/zap"
)

var (
	svc *s3.S3
)

func S3Init(role string) {
	sess := session.Must(session.NewSession())
	creds := stscreds.NewCredentials(sess, role)
	svc = s3.New(sess, &aws.Config{Region: aws.String("us-west-2"), Credentials: creds})
}

func S3NewObject(logger *zap.Logger, bucket, key string) (err error) {
	//logger := otelzap.L().Ctx(ctx)
	logger.Info("S3NewObject s3://%s/%s start...", zap.Any(bucket, key))
	defer logger.Info("S3NewObject s3://%s/%s end...", zap.Any(bucket, key), zap.Error(err))

	svc.CreateBucket(&s3.CreateBucketInput{
		Bucket: aws.String(bucket),
	})

	if err = svc.WaitUntilBucketExists(&s3.HeadBucketInput{
		Bucket: aws.String(bucket),
	}); err != nil {
		return
	}
	_, err = svc.PutObject(&s3.PutObjectInput{
		Body:   strings.NewReader(""),
		Bucket: &bucket,
		Key:    &key,
	})
	return
}

func S3KeyAppend(logger *zap.Logger, bucket, key, value string) (err error) {
	//logger := otelzap.L().Ctx(ctx)
	logger.Info("S3KeyAppend update s3://%s/%s, value len %d, start...", zap.Any(bucket, key), zap.Any("len", len(value)))
	defer logger.Info("S3KeyAppend update s3://%s/%s, value len %d, end...", zap.Any(bucket, key), zap.Any("len", len(value)), zap.Error(err))

	/* s3 object get */
	params := &s3.GetObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
	}
	resp, err := svc.GetObject(params)
	if err != nil {
		logger.Error("svc.GetObject failed.", zap.Any("params", params), zap.Error(err))
		return err
	}
	defer resp.Body.Close()

	size := int(*resp.ContentLength)
	buffer := make([]byte, size)
	var bbuffer bytes.Buffer
	for {
		num, rerr := resp.Body.Read(buffer)
		if num > 0 {
			bbuffer.Write(buffer[:num])
		} else if rerr == io.EOF || rerr != nil {
			break
		}
	}

	/* s3 object put, update object */
	params2 := &s3.PutObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
		Body:   bytes.NewReader([]byte(bbuffer.String() + value)),
	}
	_, err = svc.PutObject(params2)
	if err != nil {
		logger.Error("S3KeyAppend failed", zap.Error(err))
	}
	return
}

/*
func main() {
	if err := S3KeyAppend("dev-devtier-billing", "test-key.csv", "a,b,c,d"); err != nil {
		log.Errorf("%v", err)
	}
}
*/
