package reservedcapacitytemplate

import (
	"context"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/entity"
	reservedcapacitytemplaterepo "github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/repository/reservedcapacitytemplate"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func (s *serviceImpl) Create(
	ctx context.Context,
	req *globalngv1.CreateReservedCapacityTemplateRequest,
) (*entity.ReservedCapacityTemplate, bizerr.BizError) {
	ctx, span := tracer.Start(ctx, "Domain.CreateReservedCapacityTemplate")
	defer span.End()

	template := req.GetReservedCapacityTemplate()
	if template == nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "reserved capacity template cannot be nil")
	}
	template.Id = s.idGeneratorAdapter.MustNew()
	if template.GetStatus() == globalngv1.ReservedCapacityTemplate_STATUS_UNSPECIFIED {
		template.Status = globalngv1.ReservedCapacityTemplate_ACTIVE
	}
	if template.GetScope() == globalngv1.ReservedCapacityTemplate_SCOPE_UNSPECIFIED {
		template.Scope = globalngv1.ReservedCapacityTemplate_DEFAULT
	}
	if err := s.repo.Create(ctx, template); err != nil {
		return nil, err
	}
	return s.repo.Load(ctx, template.GetId(), false)
}

func (s *serviceImpl) Get(
	ctx context.Context,
	req *globalngv1.GetReservedCapacityTemplateRequest,
) (*entity.ReservedCapacityTemplate, bizerr.BizError) {
	ctx, span := tracer.Start(ctx, "Domain.GetReservedCapacityTemplate")
	defer span.End()

	if req.GetCapacityTemplateId() == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "reserved capacity template id cannot be empty")
	}
	return s.repo.Load(ctx, req.GetCapacityTemplateId(), false)
}

func (s *serviceImpl) List(
	ctx context.Context,
	req *globalngv1.ListReservedCapacityTemplatesRequest,
) (*globalngv1.ListReservedCapacityTemplatesResponse, bizerr.BizError) {
	ctx, span := tracer.Start(ctx, "Domain.ListReservedCapacityTemplates")
	defer span.End()

	if req.GetServicePlan() != globalcommonv1.ServicePlan_SERVICE_PLAN_UNSPECIFIED &&
		req.GetServicePlan() != globalcommonv1.ServicePlan_Premium_Reserved {
		return &globalngv1.ListReservedCapacityTemplatesResponse{}, nil
	}

	templates, total, err := s.repo.Query(ctx, &reservedcapacitytemplaterepo.Filter{
		OrganizationId: req.GetOrganizationId(),
		Status:         req.GetStatus(),
		Scope:          req.GetScope(),
		PageSize:       req.GetPageSize(),
		Page:           req.GetPage(),
	})
	if err != nil {
		return nil, err
	}
	return &globalngv1.ListReservedCapacityTemplatesResponse{
		ReservedCapacityTemplates: templates,
		Total:                     total,
	}, nil
}

func (s *serviceImpl) UpdateStatus(
	ctx context.Context,
	req *globalngv1.UpdateReservedCapacityTemplateStatusRequest,
) (*entity.ReservedCapacityTemplate, bizerr.BizError) {
	ctx, span := tracer.Start(ctx, "Domain.UpdateReservedCapacityTemplateStatus")
	defer span.End()

	if req.GetCapacityTemplateId() == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "reserved capacity template id cannot be empty")
	}
	if req.GetStatus() == globalngv1.ReservedCapacityTemplate_STATUS_UNSPECIFIED {
		return nil, bizerr.New(bizerr.ErrCodeParams, "reserved capacity template status cannot be empty")
	}
	return s.repo.UpdateStatus(ctx, req.GetCapacityTemplateId(), req.GetStatus())
}

func (s *serviceImpl) Delete(ctx context.Context, req *globalngv1.DeleteReservedCapacityTemplateRequest) bizerr.BizError {
	ctx, span := tracer.Start(ctx, "Domain.DeleteReservedCapacityTemplate")
	defer span.End()

	if req.GetCapacityTemplateId() == 0 {
		return bizerr.New(bizerr.ErrCodeParams, "reserved capacity template id cannot be empty")
	}
	return s.repo.Delete(ctx, req.GetCapacityTemplateId())
}
