package quota

import (
	"time"

	"google.golang.org/protobuf/types/known/timestamppb"
	"gorm.io/gorm"

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/infra/repoimpl/schema"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/pkg/config"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/enum"
)

func TenantQuotaModelToEn(
	tenantID uint64,
	quotasOfTenant []*schema.Quota,
	quota *config.ClusterQuota,
) (*entity.TenantClusterQuota, bizerr.BizError) {
	en := &entity.TenantClusterQuota{
		TenantID:     tenantID,
		PDQuota:      0,
		TiDBQuota:    quota.TiDB,
		TiKVQuota:    quota.TiKV,
		TiFlashQuota: quota.TiFlash,
		TiProxyQuota: quota.TiProxy,
	}
	for _, each := range quotasOfTenant {
		ct, err := enum.FromString[globaldedicatedv1.ComponentType](each.ComponentName)
		if err != nil {
			return nil, bizerr.WrapError(err, "unknown component type %s", each.ComponentName)
		}
		switch globaldedicatedv1.ComponentType(ct) {
		case globaldedicatedv1.ComponentType_TIDB:
			en.TiDBQuota = int(each.Quota)
		case globaldedicatedv1.ComponentType_TIKV:
			en.TiKVQuota = int(each.Quota)
		case globaldedicatedv1.ComponentType_TIFLASH:
			en.TiFlashQuota = int(each.Quota)
		case globaldedicatedv1.ComponentType_TIPROXY:
			en.TiProxyQuota = int(each.Quota)
		}
	}
	return en, nil
}

func tenantComponentQuotaEnToModel(en *entity.TenantComponentQuota) *schema.Quota {
	createTime := time.Now()
	if en.CreateTime != nil {
		createTime = en.CreateTime.AsTime()
	}

	return &schema.Quota{
		Model: gorm.Model{
			ID:        uint(en.ID),
			CreatedAt: createTime,
		},
		TenantID:      en.TenantID,
		ComponentName: en.ComponentName.String(),
		Quota:         en.Quota,
	}
}

func tenantComponentQuotaModel2En(m *schema.Quota) (*entity.TenantComponentQuota, error) {
	cn, err := enum.FromString[globaldedicatedv1.ComponentType](m.ComponentName)
	if err != nil {
		return nil, err
	}
	return &entity.TenantComponentQuota{
		ID:            uint64(m.ID),
		TenantID:      m.TenantID,
		ComponentName: globaldedicatedv1.ComponentType(cn),
		Quota:         m.Quota,
		CreateTime:    timestamppb.New(m.CreatedAt),
	}, nil
}
