package regionalserver

import (
	"context"
	"net/http"

	"github.com/go-resty/resty/v2"
	clusterngv1beta "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"

	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func (s *regionalServerCliImpl) ValidateSharedPoolPause(
	ctx context.Context,
	region *entity.Region,
	req *clusterngv1beta.ValidateSharedPoolPauseRequest,
) (*clusterngv1beta.ValidateSharedPoolPauseResponse, bizerr.BizError) {
	resp, berr := s.callRegion(
		ctx,
		region,
		http.MethodPost,
		operationMap["ValidateSharedPoolPause"],
		func(request *resty.Request) *resty.Request {
			request.SetPathParam(sharedPoolIdPathParameter, req.GetSharedPoolId())
			return request
		},
	)
	if berr != nil {
		return nil, berr
	}
	if resp.StatusCode() == http.StatusConflict {
		return nil, bizerr.New(bizerr.ErrCodeRegionalAPI, "regional pause validation returned conflict: %s", resp.String())
	}

	var out clusterngv1beta.ValidateSharedPoolPauseResponse
	if err := unmarshalOptions.Unmarshal(resp.Body(), &out); err != nil {
		return nil, bizerr.New(bizerr.ErrCodeRegionalAPI, "%s", err.Error())
	}
	return &out, nil
}

func (s *regionalServerCliImpl) PauseSharedPool(
	ctx context.Context,
	region *entity.Region,
	req *clusterngv1beta.PauseSharedPoolRequest,
) (*clusterngv1beta.SharedPool, bizerr.BizError) {
	return s.pauseOrResumeSharedPool(
		ctx,
		region,
		req.GetSharedPoolId(),
		req.GetOperationId(),
		operationMap["PauseSharedPool"],
	)
}

func (s *regionalServerCliImpl) ResumeSharedPool(
	ctx context.Context,
	region *entity.Region,
	req *clusterngv1beta.ResumeSharedPoolRequest,
) (*clusterngv1beta.SharedPool, bizerr.BizError) {
	return s.pauseOrResumeSharedPool(
		ctx,
		region,
		req.GetSharedPoolId(),
		req.GetOperationId(),
		operationMap["ResumeSharedPool"],
	)
}

func (s *regionalServerCliImpl) pauseOrResumeSharedPool(
	ctx context.Context,
	region *entity.Region,
	sharedPoolID string,
	operationID string,
	apiPath string,
) (*clusterngv1beta.SharedPool, bizerr.BizError) {
	resp, berr := s.callRegion(
		ctx,
		region,
		http.MethodPost,
		apiPath,
		func(request *resty.Request) *resty.Request {
			request.SetPathParam(sharedPoolIdPathParameter, sharedPoolID)
			request.SetBody(map[string]string{"operationId": operationID})
			return request
		},
	)
	if berr != nil {
		return nil, berr
	}
	if resp.StatusCode() == http.StatusConflict {
		return nil, bizerr.New(bizerr.ErrCodeRegionalAPI, "regional pause/resume returned conflict: %s", resp.String())
	}

	var out clusterngv1beta.SharedPool
	if err := unmarshalOptions.Unmarshal(resp.Body(), &out); err != nil {
		return nil, bizerr.New(bizerr.ErrCodeRegionalAPI, "%s", err.Error())
	}
	return &out, nil
}

func (s *regionalServerCliImpl) GetPauseResumeOperation(
	ctx context.Context,
	region *entity.Region,
	req *clusterngv1beta.GetPauseResumeOperationRequest,
) (*clusterngv1beta.PauseResumeOperation, bizerr.BizError) {
	resp, berr := s.callRegion(
		ctx,
		region,
		http.MethodGet,
		operationMap["GetPauseResumeOperation"],
		func(request *resty.Request) *resty.Request {
			request.SetPathParam(sharedPoolIdPathParameter, req.GetSharedPoolId())
			request.SetPathParam("operationId", req.GetOperationId())
			return request
		},
	)
	if berr != nil {
		if resp != nil && resp.StatusCode() == http.StatusNotFound {
			return nil, bizerr.New(bizerr.ErrCodeRecordNotFound, "pause/resume operation not found")
		}
		return nil, berr
	}
	if resp.StatusCode() == http.StatusConflict {
		return nil, bizerr.New(bizerr.ErrCodeRegionalAPI, "regional pause/resume operation returned conflict: %s", resp.String())
	}

	var out clusterngv1beta.PauseResumeOperation
	if err := unmarshalOptions.Unmarshal(resp.Body(), &out); err != nil {
		return nil, bizerr.New(bizerr.ErrCodeRegionalAPI, "%s", err.Error())
	}
	return &out, nil
}
