package cluster

import (
	"context"

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/adapter/account"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/quota"
	clustersvc "github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/service/cluster"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func (s *server) ListTenantQuota(
	ctx context.Context,
	request *globaldedicatedv1.ListTenantQuotaRequest,
) (*globaldedicatedv1.ListTenantQuotaResponse, error) {
	resp := &globaldedicatedv1.ListTenantQuotaResponse{}

	if request.TenantId == 0 {
		return resp, bizerr.New(bizerr.ErrCodeParams, "filter is required")
	}

	out := make([]*globaldedicatedv1.TenantQuota, 0)
	for ct := range entity.ComponentsUserEditable {
		out = append(out, &globaldedicatedv1.TenantQuota{
			Component: ct,
			Quota:     0,
			TenantId:  request.TenantId,
		})
	}

	items, err := s.tenantQuotaRepo.Query(ctx, quota.TenantQuotaFilter{
		TenantID: request.TenantId,
	})
	if err != nil {
		return resp, err
	}

	for _, o := range out {
		for _, i := range items {
			if cpt := i.ComponentName; cpt == o.Component {
				o.Quota = i.Quota
				o.Id = i.ID
				break
			}
		}
	}

	resp.TenantQuotas = out

	return resp, nil
}

func (s *server) UpdateTenantQuota(
	ctx context.Context,
	request *globaldedicatedv1.UpdateTenantQuotaRequest,
) (*globaldedicatedv1.UpdateTenantQuotaResponse, error) {
	resp := &globaldedicatedv1.UpdateTenantQuotaResponse{}

	if err := s.check(ctx, request); err != nil {
		return resp, err
	}

	if err := s.updateTenantQuotaSvc.Execute(ctx, &clustersvc.UpdateTenantQuotaParams{
		TenantID:  request.TenantId,
		Component: request.Component,
		Quota:     request.Quota,
	}); err != nil {
		return resp, bizerr.WrapError(err, "transaction")
	}

	return resp, nil
}

func (s *server) check(ctx context.Context, req *globaldedicatedv1.UpdateTenantQuotaRequest) bizerr.BizError {
	if req.TenantId == 0 {
		return bizerr.New(bizerr.ErrCodeParams, "invalid tenant id")
	}

	info, err := s.tenantFacade.QueryTenant(ctx, account.TenantFilter{
		TenantIDs: []uint64{req.TenantId},
	})
	if err != nil {
		return err
	}

	if len(info) == 0 {
		return bizerr.New(bizerr.ErrCodeParams, "not found the tenant")
	}

	if _, ok := entity.ComponentsUserEditable[req.Component]; !ok {
		return bizerr.New(bizerr.ErrCodeParams, "unsupported component type: %v", req.Component)
	}

	return nil
}
