// Package repository_ddb add by blacknc <blacknc@163.com> at 2023/04/10 17:03:48
package repository_ddb

import (
	"context"
	"dataservices/commons/config"
	"dataservices/ddb"
	"dataservices/internal/entity"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

func getDDBTableName(table string) string {
	env := config.Global().ServerConf.Env
	if env == "prod" {
		return table
	}
	return table + "_" + env
}

func appClusterTable() string {
	return getDDBTableName(entity.TableDataAppClusters)
}

func userClusterTable() string {
	return getDDBTableName(entity.TableUserClusterInfo)
}

func dataappsTable() string {
	return getDDBTableName(entity.TableDataApps)
}

func endpointsTable() string {
	return getDDBTableName(entity.TableEndpoints)
}

func endpointPublishTable() string {
	return getDDBTableName(entity.TableEndpointPublish)
}

func customDomainTable() string {
	return getDDBTableName(entity.TableCustomDomain)
}

func DataappsTable() string {
	return dataappsTable()
}
func EndpointsTable() string {
	return endpointsTable()
}
func EndpointPublishTable() string {
	return endpointPublishTable()
}
func AppClusterTable() string {
	return appClusterTable()
}

type Key struct {
	Name string
	Type types.ScalarAttributeType
}

func genTableSchema(tableName string, partitionKey types.AttributeDefinition, sortKey *types.AttributeDefinition) *dynamodb.CreateTableInput {
	createTableInput := &dynamodb.CreateTableInput{
		AttributeDefinitions: []types.AttributeDefinition{partitionKey},
		KeySchema: []types.KeySchemaElement{{
			AttributeName: partitionKey.AttributeName,
			KeyType:       types.KeyTypeHash,
		}},
		TableName: aws.String(tableName),
		//ProvisionedThroughput: &types.ProvisionedThroughput{
		//	ReadCapacityUnits:  aws.Int64(10),
		//	WriteCapacityUnits: aws.Int64(10),
		//},
		BillingMode: types.BillingModePayPerRequest,
	}
	if sortKey != nil {
		createTableInput.AttributeDefinitions = append(createTableInput.AttributeDefinitions, *sortKey)
		createTableInput.KeySchema = append(createTableInput.KeySchema, types.KeySchemaElement{
			AttributeName: sortKey.AttributeName,
			KeyType:       types.KeyTypeRange,
		})
	}
	return createTableInput
}

func createGlobalTable(ctx context.Context, cli *dynamodb.Client, createTableInput *dynamodb.CreateTableInput, replicaRegions []string) error {

	tableName := *createTableInput.TableName
	if err := createTableIfNotExist(ctx, cli, createTableInput); err != nil {
		return errs.NewInternalDB("Failed to create table: "+tableName, err)
	}
	if err := ddb.CreateGlobalTable(ctx, cli, tableName, replicaRegions); err != nil {
		return errs.NewInternalDB("Failed to create replica table: "+tableName, err)
	}
	return nil
}

func deleteGlobalTable(ctx context.Context, cli *dynamodb.Client, tableName string, replicaRegions []string) error {

	if err := ddb.DeleteTable(ctx, cli, tableName); err != nil {
		return errs.NewInternalDB("Failed to delete table: "+tableName, err)
	}
	if err := ddb.DeleteGlobalTable(ctx, cli, tableName, replicaRegions); err != nil {
		return errs.NewInternalDB("Failed to delete replica table: "+tableName, err)
	}
	return nil
}

func createTableIfNotExist(ctx context.Context, cli *dynamodb.Client, createTableInput *dynamodb.CreateTableInput) error {
	tableName := *createTableInput.TableName
	exist, err := ddb.IsTableExist(ctx, cli, tableName)
	if err != nil || exist {
		tilog.Info(ctx, "Table may be already exist", zap.String("table", tableName), zap.Error(err))
		return err
	}
	_, err = ddb.CreateTableForGlobal(ctx, cli, createTableInput)
	return err
}
