package tidbgroup

import (
	"context"

	"google.golang.org/protobuf/types/known/emptypb"

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	tidbgroupsvc "github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/service/tidbgroup"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func NewServer(
	tidbGroupSvc tidbgroupsvc.Service,
) globaldedicatedv1.TidbNodeGroupServiceServer {
	return &server{
		tidbGroupSvc: tidbGroupSvc,
	}
}

type server struct {
	tidbGroupSvc tidbgroupsvc.Service
}

func (s *server) CreateTidbNodeGroup(
	ctx context.Context,
	request *globaldedicatedv1.CreateTidbNodeGroupRequest,
) (*globaldedicatedv1.TidbNodeGroup, error) {
	if request.TidbNodeGroup == nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "tidb_node_group is required")
	}

	if request.TidbNodeGroup.ClusterId == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "cluster_id is required")
	}

	tidbGroup, err := s.tidbGroupSvc.CreateTidbNodeGroup(ctx, request)
	if err != nil {
		return nil, err
	}

	return tidbGroup, nil
}

func (s *server) UpdateTidbNodeGroup(
	ctx context.Context,
	request *globaldedicatedv1.UpdateTidbNodeGroupRequest,
) (*globaldedicatedv1.TidbNodeGroup, error) {
	if request.TidbNodeGroup == nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "tidb_node_group is required")
	}
	if request.TidbNodeGroup.Id == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "id is required")
	}

	tidbGroup, err := s.tidbGroupSvc.UpdateTidbNodeGroup(ctx, request)
	if err != nil {
		return nil, err
	}

	return tidbGroup, nil
}

func (s *server) DeleteTidbNodeGroup(
	ctx context.Context,
	request *globaldedicatedv1.DeleteTidbNodeGroupRequest,
) (*emptypb.Empty, error) {
	if request.Id == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "id is required")
	}

	if _, err := s.tidbGroupSvc.DeleteTidbNodeGroup(ctx, request); err != nil {
		return nil, err
	}

	return &emptypb.Empty{}, nil
}

func (s *server) ListTidbNodeGroups(
	ctx context.Context,
	request *globaldedicatedv1.ListTidbNodeGroupsRequest,
) (*globaldedicatedv1.ListTidbNodeGroupsResponse, error) {
	if len(request.ClusterIds) == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "cluster_ids filter is required")
	}

	tidbGroups, err := s.tidbGroupSvc.ListTidbNodeGroups(ctx, request)
	if err != nil {
		return nil, err
	}

	return tidbGroups, nil
}

func (s *server) DisableTidbGroupDNS(
	ctx context.Context,
	request *globaldedicatedv1.DisableTidbGroupDNSRequest,
) (*emptypb.Empty, error) {
	if request.GetClusterId() == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "cluster_id is required")
	}
	if request.GetTidbGroupId() == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "tidb_group_id is required")
	}

	result, err := s.tidbGroupSvc.DisableTidbGroupDNS(ctx, request)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (s *server) EnableTidbGroupDNS(
	ctx context.Context,
	request *globaldedicatedv1.EnableTidbGroupDNSRequest,
) (*emptypb.Empty, error) {
	if request.GetClusterId() == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "cluster_id is required")
	}
	if request.GetTidbGroupId() == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "tidb_group_id is required")
	}

	result, err := s.tidbGroupSvc.EnableTidbGroupDNS(ctx, request)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (s *server) GetPrivateLinkIPAddressType(
	ctx context.Context,
	request *globaldedicatedv1.GetPrivateLinkIPAddressTypeRequest,
) (*globaldedicatedv1.TidbGroupPrivateLinkIPAddressTypeStatus, error) {
	return s.tidbGroupSvc.GetPrivateLinkIPAddressType(ctx, request)
}

func (s *server) SetPrivateLinkIPAddressType(
	ctx context.Context,
	request *globaldedicatedv1.SetPrivateLinkIPAddressTypeRequest,
) (*globaldedicatedv1.TidbGroupPrivateLinkIPAddressTypeStatus, error) {
	return s.tidbGroupSvc.SetPrivateLinkIPAddressType(ctx, request)
}
