package repoter

import (
	"context"
	"encoding/json"
	"os"
	"testing"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/sqs"
	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/metering/pkg/common/constants"
	"github.com/tidbcloud/metering/pkg/common/models"
	"github.com/tidbcloud/metering/test/mockrepoter"
	"go.uber.org/mock/gomock"
)

func TestFromJson(t *testing.T) {
	s := `{"projectID":"1234","startTime":"2024-01-01T00:00:00Z","endTime":"2024-01-02T00:00:00Z"}`
	result, err := fromjson(s)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, "1234", result[constants.TagBillingProjectID])
	assert.Equal(t, "2024-01-01T00:00:00Z", result["startTime"])
	assert.Equal(t, "2024-01-02T00:00:00Z", result["endTime"])

}

func TestSkipClusterID(t *testing.T) {
	ctrl := gomock.NewController(t)
	sqscli := mockrepoter.NewMocksqsClient(ctrl)
	var sender = new(MeasureAPIImpl)
	os.Setenv("AWS_ROLE_ARN", "arn:aws")
	err := sender.InitMeasureHandler("dev", "gcp", true, true)
	assert.Nil(t, err)
	repoter := models.BillingReport{
		TenantID:      123,
		CostID:        "123",
		Cost:          100000000,
		CostTimestamp: 1723487507,
		Labels:        `{"projectID":"123","clusterID":"123"}`,
		Unit:          "network-traffic:aws:us-east-1:cross_region",
		CreatedAt:     1723487507,
	}
	sender.MeasureSQSImpl.sqsClient = sqscli
	tmp := models.BillingReportSender{
		TenantID:      repoter.TenantID,
		CostID:        repoter.CostID,
		Cost:          repoter.Cost,
		CostTimestamp: repoter.CostTimestamp,
		Unit:          repoter.Unit,
	}
	lables, err := fromjson(repoter.Labels)
	assert.Nil(t, err)
	delete(lables, constants.TagBillingClusterID)
	tmp.Labels = lables
	jsonData, err := json.Marshal(tmp)
	assert.Nil(t, err)
	sqscli.EXPECT().SendMessage(gomock.Any(), &sqs.SendMessageInput{
		MessageBody:  aws.String(string(jsonData)),
		QueueUrl:     aws.String("https://sqs.us-west-2.amazonaws.com/385595570414/billing-report-nightly"),
		DelaySeconds: 0,
	}).Return(nil, nil)

	err = sender.SendMeasure(context.TODO(), repoter)
	assert.Nil(t, err)
}

func TestSendSQS(t *testing.T) {
	ctrl := gomock.NewController(t)
	sqscli := mockrepoter.NewMocksqsClient(ctrl)
	var sender = new(MeasureAPIImpl)
	os.Setenv("AWS_ROLE_ARN", "arn:aws")
	err := sender.InitMeasureHandler("dev", "aws", true, true)
	assert.Nil(t, err)
	repoter := models.BillingReport{
		TenantID:      123,
		CostID:        "123",
		Cost:          100000000,
		CostTimestamp: 1723487507,
		Labels:        `{"projectID":"123","clusterID":"123"}`,
		Unit:          "network-traffic:aws:us-east-1:cross_region",
		CreatedAt:     1723487507,
	}
	sender.MeasureSQSImpl.sqsClient = sqscli
	sqscli.EXPECT().SendMessage(gomock.Any(), gomock.Any()).Return(nil, nil)
	err = sender.SendMeasure(context.TODO(), repoter)
	assert.Nil(t, err)
}

func TestCheckMeasure_Failure(t *testing.T) {
	var sender = new(MeasureAPIImpl)
	// tenant id is 0
	err := sender.CheckMeasure(models.BillingReport{
		TenantID: 0,
	})
	assert.NotNil(t, err)
	// cost id is 0
	err = sender.CheckMeasure(models.BillingReport{
		TenantID: 123,
		CostID:   "0",
	})
	assert.NotNil(t, err)
	//cost is 0
	err = sender.CheckMeasure(models.BillingReport{
		TenantID: 123,
		CostID:   "123",
		Cost:     0,
	})
	assert.NotNil(t, err)
	//cost timestamp is 0
	err = sender.CheckMeasure(models.BillingReport{
		TenantID:      123,
		CostID:        "123",
		Cost:          100000000,
		CostTimestamp: 0,
	})
	assert.NotNil(t, err)
	//unit is empty
	err = sender.CheckMeasure(models.BillingReport{
		TenantID:      123,
		CostID:        "123",
		Cost:          100000000,
		CostTimestamp: 1723487507,
		Unit:          "",
	})
	assert.NotNil(t, err)
}

func TestAPIInitMeasureHandler(t *testing.T) {
	var sender = new(MeasureAPIImpl)
	err := sender.InitMeasureHandler("dev", "aws", true, false, "testurl")
	assert.Nil(t, err)
	// test envType is invalid
	err = sender.InitMeasureHandler("", "aws", true, false, "testurl")
	assert.NotNil(t, err)
	//apiurl is empty
	err = sender.InitMeasureHandler("dev", "aws", true, false)
	assert.Nil(t, err)
}

func TestSQSInitMeasureHandler(t *testing.T) {
	os.Setenv("AWS_ROLE_ARN", "arn:aws")
	defer os.Unsetenv("AWS_ROLE_ARN")
	var sender = new(MeasureAPIImpl)
	// test envType is empty
	err := sender.InitMeasureHandler("", "aws", true, true)
	assert.NotNil(t, err)
	// test envType is invalid
	err = sender.InitMeasureHandler("invalid", "aws", true, true)
	assert.NotNil(t, err)
	//test has url
	err = sender.InitMeasureHandler("dev", "aws", true, true, "testurl")
	assert.Nil(t, err)
}
