package jobs

import (
	"context"
	"fmt"
	"sort"
	"strings"

	"github.com/fatih/color"
	"github.com/rodaine/table"
	"github.com/shopspring/decimal"
	"github.com/tidbcloud/dataflow-service/pkg/billing"
	"github.com/tidbcloud/dataflow-service/pkg/log"
	"go.uber.org/zap"
)

const (
	oldSingleRegionStorageCategory = "Backup Cost"

	singleRegionStorageCategory = "Single Region Storage"

	dualRegionStorageCategory = "Dual Region Storage"

	// sku resource type
	dualRegionStorageResourceType     = "backup-dual-region-storage"
	dualRegionReplicationResourceType = "backup-dual-region-replication"
)

func isBackupCostSku(sku *billing.SKU) bool {
	return sku.Category == oldSingleRegionStorageCategory
}

func isSingleRegionStorageSku(sku *billing.SKU) bool {
	return sku.Category == singleRegionStorageCategory
}

func isDualRegionStorageSku(sku *billing.SKU) bool {
	return strings.Contains(sku.UnitKey, dualRegionStorageResourceType)
}

func isReplicationSku(sku *billing.SKU) bool {
	return strings.Contains(sku.UnitKey, dualRegionReplicationResourceType)
}

func getBackupSkuListByActiveSku(ctx context.Context) ([]*billing.SKU, error) {
	c := billing.GetHandler()
	skuList, err := c.ListSKU(ctx)
	if err != nil {
		return nil, err
	}
	// filter not related sku
	brSkuList := []*billing.SKU{}
	for _, sku := range skuList {
		if isBackupCostSku(sku) ||
			isSingleRegionStorageSku(sku) ||
			isDualRegionStorageSku(sku) ||
			isReplicationSku(sku) {
			brSkuList = append(brSkuList, sku)
		}
	}
	return brSkuList, nil
}

func ListAllBackupSKU(ctx context.Context) error {
	logger := log.GetLogger(ctx).Named("ListAllBackupSKU")
	brSkuList, err := getBackupSkuListByActiveSku(ctx)
	if err != nil {
		logger.Error("list sku failed", zap.Error(err))
	}

	headerFmt := color.New(color.FgGreen, color.Underline).SprintfFunc()
	columnFmt := color.New(color.FgYellow).SprintfFunc()

	tbl := table.New("Category", "Provider", "Region", "Price", "UnitKey")
	tbl.WithHeaderFormatter(headerFmt).WithFirstColumnFormatter(columnFmt)

	// sort by category and provider
	sort.Slice(brSkuList, func(i, j int) bool {
		if brSkuList[i].Category == brSkuList[j].Category {
			return brSkuList[i].Provider < brSkuList[j].Provider
		}
		return brSkuList[i].Category < brSkuList[j].Category
	})

	for _, sku := range brSkuList {
		tbl.AddRow(sku.Category, sku.Provider, sku.Region, sku.Price, sku.UnitKey)
	}
	tbl.Print()
	return nil
}

func addNewSku(ctx context.Context, provider, region, price, resType, category string) error {
	logger := log.GetLogger(ctx).Named("AddNewSkuToAllRegion")
	c := billing.GetHandler()

	sku := &billing.SKU{
		UnitKey:  fmt.Sprintf("%s:%s:%s", resType, provider, region),
		Region:   region,
		Provider: strings.ToUpper(provider), // AWS or GCP
		Category: category,
		Price:    decimal.RequireFromString(price),
	}

	new, err := c.CreateOrUpdateSKU(ctx, sku)
	if err != nil {
		logger.Error("create sku failed", zap.Error(err))
		return err
	}
	logger.Info("create sku success", zap.String("sku key", new.UnitKey), zap.String("sku category", new.Category))
	return nil
}

func AddDualRegionBackupStorageSku(ctx context.Context, cloudProvider string, region string, price string) error {
	//if err := addNewSku(
	//	ctx, "aws", "ap-northeast-3", "0.000004977166667", dualRegionStorageResourceType, dualRegionStorageCategory); err != nil {
	//	return err
	//}
	//if err := addNewSku(
	//	ctx, "gcp", "us-east4", "0.0000050228", dualRegionStorageResourceType, dualRegionStorageCategory); err != nil {
	//	return err
	//}
	if err := addNewSku(
		ctx, cloudProvider, region, price, dualRegionStorageResourceType, dualRegionStorageCategory); err != nil {
		return err
	}
	return nil
}

func AddDualRegionBackupReplicationSku(ctx context.Context, cloudProvider string, region string, price string) error {
	//if err := addNewSku(
	//	ctx, "aws", "ap-northeast-3", "0.09", dualRegionReplicationResourceType, "Data Transfer Cost - AWS Cross Region"); err != nil {
	//	return err
	//}
	//if err := addNewSku(
	//	ctx, "gcp", "us-east4", "0.02", dualRegionReplicationResourceType, "Data Transfer Cost - GCP Cross Region"); err != nil {
	//	return err
	//}
	var category string
	if cloudProvider == "aws" {
		category = "Data Transfer Cost - AWS Cross Region"
	} else if cloudProvider == "gcp" {
		category = "Data Transfer Cost - GCP Cross Region"
	} else {
		return fmt.Errorf("invalid cloud provider: %s", cloudProvider)
	}
	if err := addNewSku(
		ctx, cloudProvider, region, price, dualRegionReplicationResourceType, category); err != nil {
		return err
	}
	return nil
}
