package facade

import (
	"context"

	tidb_mgmt_servicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"

	"github.com/tidbcloud/metering/pkg/common/config"
	"github.com/tidbcloud/metering/pkg/common/constants"
	"github.com/tidbcloud/metering/pkg/facade/iface"
	"github.com/tidbcloud/metering/pkg/facade/mgmt"
	"github.com/tidbcloud/metering/pkg/facade/s3storage"
	"github.com/tidbcloud/metering/pkg/repoter"
)

var metaQuerier iface.TiDBClusterMetaQuerier
var dataSync iface.ScheduleTaskDataSync
var checkpointRW iface.CheckpointReaderWriter
var sender repoter.MeasureSender

func GetCheckpointReaderWriter(ctx context.Context) iface.CheckpointReaderWriter {
	if checkpointRW == nil {
		bucket := config.GetConfig().Bucket
		checkpointRW = s3storage.BuildS3Checkpoint(bucket, constants.S3DataPrefix, getS3Client())
	}
	return checkpointRW
}

func GetScheduleTaskDataSync(ctx context.Context) iface.ScheduleTaskDataSync {
	if dataSync == nil {
		bucket := config.GetConfig().Bucket
		dataSync = s3storage.BuildS3ScheduleTaskData(bucket, constants.S3DataPrefix, "sqlite", getS3Client(), "data")
	}
	return dataSync
}

func GetTiDBClusterMetaQuerier(ctx context.Context) iface.TiDBClusterMetaQuerier {
	if metaQuerier == nil {
		conn, err := grpc.NewClient(config.GetConfig().InstanceMeteringConfig.MgmtGrpcTarget, grpc.WithTransportCredentials(insecure.NewCredentials()))
		if err != nil {
			panic(err.Error())
		}

		serviceClient := tidb_mgmt_servicev1.NewClusterServiceClient(conn)

		metaQuerier = mgmt.NewTiDBMgmtGrpcService(ctx, serviceClient)
	}

	return metaQuerier
}

func GetMeasureSender(ctx context.Context) repoter.MeasureSender {
	if sender == nil {
		var s repoter.MeasureSender = new(repoter.MeasureAPIImpl)

		err := s.InitMeasureHandler(config.GetConfig().Env, config.GetConfig().Vendor, false, true)
		if err != nil {
			panic(err)
		}
		sender = s
	}
	return sender
}

var cli s3storage.Client

// todo configs
func getS3Client() s3storage.Client {
	if cli != nil {
		return cli
	}
	cli = s3storage.PrepareS3Client(context.TODO(), config.GetConfig().Vendor, config.GetConfig().Region, "")
	return cli
}

func MockCheckpointReaderWriter(mock iface.CheckpointReaderWriter) {
	checkpointRW = mock
}

func MockScheduleTaskDataSync(mock iface.ScheduleTaskDataSync) {
	dataSync = mock
}

func MockTiDBClusterMetaQuerier(mock iface.TiDBClusterMetaQuerier) {
	metaQuerier = mock
}

func MockMeasureSender(mock repoter.MeasureSender) {
	sender = mock
}
