package resourcemanager

import (
	"bytes"
	"context"
	"io"
	"strings"
	"testing"

	s3api "github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/observability/pkg/common/errors"
	"github.com/tidbcloud/observability/pkg/common/structs"
	awsclient "github.com/tidbcloud/observability/pkg/resourceworker/providers/aws"
	mocks "github.com/tidbcloud/observability/test/mockresourceworker/providers/aws"
	"go.uber.org/mock/gomock"
	"gopkg.in/yaml.v3"
)

func Test_archivedClusterReaderWriter_Archive(t *testing.T) {
	ctl := gomock.NewController(t)
	defer ctl.Finish()

	mockclient := mocks.NewMocks3Client(ctl)

	archivedClusterRW = archivedClusterReaderWriter{
		s3Cli: awsclient.MockS3(mockclient),
	}

	mockclient.EXPECT().PutObject(gomock.Any(), gomock.Any()).Return(nil, errors.New(errors.UnrecognizedError, ""))

	err := archivedClusterRW.Archive(context.TODO(), "test", structs.ClusterUniqueKey{}, structs.ArchivedClusterInfo{})
	assert.Error(t, err)

	mockclient.EXPECT().PutObject(gomock.Any(), gomock.Any()).Return(&s3api.PutObjectOutput{}, nil)
	err = archivedClusterRW.Archive(context.TODO(), "test", structs.ClusterUniqueKey{}, structs.ArchivedClusterInfo{})
	assert.NoError(t, err)
}

func Test_archivedClusterReaderWriter_Get(t *testing.T) {
	ctl := gomock.NewController(t)
	defer ctl.Finish()

	mockclient := mocks.NewMocks3Client(ctl)

	archivedClusterRW = archivedClusterReaderWriter{
		s3Cli: awsclient.MockS3(mockclient),
	}

	mockclient.EXPECT().GetObject(gomock.Any(), gomock.Any()).Return(nil, errors.New(errors.UnrecognizedError, ""))

	_, err := archivedClusterRW.Get(context.TODO(), "test", structs.ClusterUniqueKey{})
	assert.Error(t, err)
	assert.Equal(t, errors.UnrecognizedError, err.(errors.Error).Code())

	mockclient.EXPECT().GetObject(gomock.Any(), gomock.Any()).Return(&s3api.GetObjectOutput{
		Body: io.NopCloser(strings.NewReader("sss")),
	}, nil)
	_, err = archivedClusterRW.Get(context.TODO(), "test", structs.ClusterUniqueKey{})
	assert.Error(t, err)
	assert.Equal(t, errors.UnmarshalError, err.(errors.Error).Code())

	tt := structs.ArchivedClusterInfo{
		VMAccountID: "111",
	}
	content, err := yaml.Marshal(tt)
	assert.NoError(t, err)

	mockclient.EXPECT().GetObject(gomock.Any(), gomock.Any()).Return(&s3api.GetObjectOutput{
		Body: io.NopCloser(bytes.NewReader(content)),
	}, nil)
	r, err := archivedClusterRW.Get(context.TODO(), "test", structs.ClusterUniqueKey{})
	assert.NoError(t, err)
	assert.Equal(t, "111", r.VMAccountID)
}

func Test_buildObjectStorageKey(t *testing.T) {
	assert.Equal(t, "archived/1/2/3/4/cluster.yaml", buildObjectStorageKey(structs.ClusterUniqueKey{
		BizType:       "1",
		TenantID:      "2",
		ProjectID:     "3",
		ApplicationID: "4",
	}))
}
