package storage

import (
	"bytes"
	"context"
	"io"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/pingcap/errors"

	"github.com/tidbcloud/observability/pkg/diagcontroller/helper"
)

type S3Storage struct {
	cli *s3.Client
}

func NewS3Storage(region string) (Storage, error) {
	cli, err := helper.NewS3Cli(region)
	if err != nil {
		return nil, err
	}
	return &S3Storage{
		cli: cli,
	}, nil
}

func (s *S3Storage) LoadObject(bucket string, key string) ([]byte, error) {
	resp, err := s.cli.GetObject(context.TODO(), &s3.GetObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
	})
	if err != nil {
		return nil, errors.Annotatef(err, "get object from s3 failed, bucket: %s, object key: %s", bucket, key)
	}
	defer resp.Body.Close()
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Annotatef(err, "read object from s3 failed, bucket: %s, object key: %s", bucket, key)
	}
	return data, nil
}

func (s *S3Storage) UploadObject(bucket string, key string, data []byte) error {
	_, err := s.cli.PutObject(context.TODO(), &s3.PutObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
		Body:   bytes.NewReader(data),
	})

	if err != nil {
		return errors.Annotatef(err, "upload object to s3 failed bucket: %s, object key: %s", bucket, key)
	}
	return nil
}
