package regionalserver

import (
	"context"
	"encoding/json"
	"net/http"
	"strings"

	"github.com/go-resty/resty/v2"

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

type checkRequestBody struct {
	TargetType string                          `json:"targetType"`
	Kms        *regionalserver.CheckKmsRequest `json:"kms"`
}

func (s *regionalServerCliImpl) CheckKms(
	ctx context.Context,
	region *entity.Region,
	req *regionalserver.CheckKmsRequest,
) bizerr.BizError {
	if req.SharedPoolId == "" {
		return bizerr.New(bizerr.ErrCodeParams, "shared pool id is required for kms check")
	}
	body, err := json.Marshal(&checkRequestBody{TargetType: "kms", Kms: req})
	if err != nil {
		return bizerr.New(bizerr.ErrCodeJsonMarshal, "%s", err.Error())
	}
	resp, bErr := s.callRegion(
		ctx,
		region,
		http.MethodPost,
		operationMap["CheckKms"],
		func(request *resty.Request) *resty.Request {
			request.SetPathParam(sharedPoolIdPathParameter, req.SharedPoolId)
			request.SetBody(body)
			return request
		},
	)
	if bErr != nil && resp != nil {
		return regionalResponseBizError(resp, bErr)
	}
	return bErr
}

func regionalResponseBizError(resp *resty.Response, bErr bizerr.BizError) bizerr.BizError {
	return bErr.
		OverwriteCode(regionalStatusBizErrCode(resp.StatusCode())).
		OverwriteMessage("%s", regionalResponseErrorMessage(resp, bErr))
}

func regionalStatusBizErrCode(status int) bizerr.ErrCode {
	if status >= http.StatusInternalServerError {
		return bizerr.ErrCodeRegionalAPI
	}
	if code, ok := bizerr.HttpStatus2BizErrCode[status]; ok {
		return code
	}
	if status >= http.StatusBadRequest {
		return bizerr.ErrCodeParams
	}
	return bizerr.ErrCodeRegionalAPI
}

func regionalResponseErrorMessage(resp *resty.Response, bErr bizerr.BizError) string {
	var body struct {
		Error   string `json:"error"`
		Message string `json:"message"`
	}
	if err := json.Unmarshal(resp.Body(), &body); err == nil {
		if body.Error != "" {
			return body.Error
		}
		if body.Message != "" {
			return body.Message
		}
	}
	if msg := strings.TrimSpace(resp.String()); msg != "" {
		return msg
	}
	return bErr.ErrMsg()
}
