//go:build go1.18
// +build go1.18

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

package armbilling

import (
	"context"
	"errors"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)

// SavingsPlansClient contains the methods for the SavingsPlans group.
// Don't use this type directly, use NewSavingsPlansClient() instead.
type SavingsPlansClient struct {
	internal *arm.Client
}

// NewSavingsPlansClient creates a new instance of SavingsPlansClient with the specified values.
//   - credential - used to authorize requests. Usually a credential from azidentity.
//   - options - pass nil to accept the default values.
func NewSavingsPlansClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*SavingsPlansClient, error) {
	cl, err := arm.NewClient(moduleName, moduleVersion, credential, options)
	if err != nil {
		return nil, err
	}
	client := &SavingsPlansClient{
		internal: cl,
	}
	return client, nil
}

// GetByBillingAccount - Get savings plan by billing account.
// If the operation fails it returns an *azcore.ResponseError type.
//
// Generated from API version 2024-04-01
//   - billingAccountName - The ID that uniquely identifies a billing account.
//   - savingsPlanOrderID - Order ID of the savings plan
//   - savingsPlanID - ID of the savings plan
//   - options - SavingsPlansClientGetByBillingAccountOptions contains the optional parameters for the SavingsPlansClient.GetByBillingAccount
//     method.
func (client *SavingsPlansClient) GetByBillingAccount(ctx context.Context, billingAccountName string, savingsPlanOrderID string, savingsPlanID string, options *SavingsPlansClientGetByBillingAccountOptions) (SavingsPlansClientGetByBillingAccountResponse, error) {
	var err error
	const operationName = "SavingsPlansClient.GetByBillingAccount"
	ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, operationName)
	ctx, endSpan := runtime.StartSpan(ctx, operationName, client.internal.Tracer(), nil)
	defer func() { endSpan(err) }()
	req, err := client.getByBillingAccountCreateRequest(ctx, billingAccountName, savingsPlanOrderID, savingsPlanID, options)
	if err != nil {
		return SavingsPlansClientGetByBillingAccountResponse{}, err
	}
	httpResp, err := client.internal.Pipeline().Do(req)
	if err != nil {
		return SavingsPlansClientGetByBillingAccountResponse{}, err
	}
	if !runtime.HasStatusCode(httpResp, http.StatusOK) {
		err = runtime.NewResponseError(httpResp)
		return SavingsPlansClientGetByBillingAccountResponse{}, err
	}
	resp, err := client.getByBillingAccountHandleResponse(httpResp)
	return resp, err
}

// getByBillingAccountCreateRequest creates the GetByBillingAccount request.
func (client *SavingsPlansClient) getByBillingAccountCreateRequest(ctx context.Context, billingAccountName string, savingsPlanOrderID string, savingsPlanID string, options *SavingsPlansClientGetByBillingAccountOptions) (*policy.Request, error) {
	urlPath := "/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/savingsPlanOrders/{savingsPlanOrderId}/savingsPlans/{savingsPlanId}"
	if billingAccountName == "" {
		return nil, errors.New("parameter billingAccountName cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{billingAccountName}", url.PathEscape(billingAccountName))
	if savingsPlanOrderID == "" {
		return nil, errors.New("parameter savingsPlanOrderID cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{savingsPlanOrderId}", url.PathEscape(savingsPlanOrderID))
	if savingsPlanID == "" {
		return nil, errors.New("parameter savingsPlanID cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{savingsPlanId}", url.PathEscape(savingsPlanID))
	req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath))
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("api-version", "2024-04-01")
	if options != nil && options.Expand != nil {
		reqQP.Set("expand", *options.Expand)
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header["Accept"] = []string{"application/json"}
	return req, nil
}

// getByBillingAccountHandleResponse handles the GetByBillingAccount response.
func (client *SavingsPlansClient) getByBillingAccountHandleResponse(resp *http.Response) (SavingsPlansClientGetByBillingAccountResponse, error) {
	result := SavingsPlansClientGetByBillingAccountResponse{}
	if err := runtime.UnmarshalAsJSON(resp, &result.SavingsPlanModel); err != nil {
		return SavingsPlansClientGetByBillingAccountResponse{}, err
	}
	return result, nil
}

// NewListByBillingAccountPager - List savings plans by billing account.
//
// Generated from API version 2024-04-01
//   - billingAccountName - The ID that uniquely identifies a billing account.
//   - options - SavingsPlansClientListByBillingAccountOptions contains the optional parameters for the SavingsPlansClient.NewListByBillingAccountPager
//     method.
func (client *SavingsPlansClient) NewListByBillingAccountPager(billingAccountName string, options *SavingsPlansClientListByBillingAccountOptions) *runtime.Pager[SavingsPlansClientListByBillingAccountResponse] {
	return runtime.NewPager(runtime.PagingHandler[SavingsPlansClientListByBillingAccountResponse]{
		More: func(page SavingsPlansClientListByBillingAccountResponse) bool {
			return page.NextLink != nil && len(*page.NextLink) > 0
		},
		Fetcher: func(ctx context.Context, page *SavingsPlansClientListByBillingAccountResponse) (SavingsPlansClientListByBillingAccountResponse, error) {
			ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "SavingsPlansClient.NewListByBillingAccountPager")
			nextLink := ""
			if page != nil {
				nextLink = *page.NextLink
			}
			resp, err := runtime.FetcherForNextLink(ctx, client.internal.Pipeline(), nextLink, func(ctx context.Context) (*policy.Request, error) {
				return client.listByBillingAccountCreateRequest(ctx, billingAccountName, options)
			}, nil)
			if err != nil {
				return SavingsPlansClientListByBillingAccountResponse{}, err
			}
			return client.listByBillingAccountHandleResponse(resp)
		},
		Tracer: client.internal.Tracer(),
	})
}

// listByBillingAccountCreateRequest creates the ListByBillingAccount request.
func (client *SavingsPlansClient) listByBillingAccountCreateRequest(ctx context.Context, billingAccountName string, options *SavingsPlansClientListByBillingAccountOptions) (*policy.Request, error) {
	urlPath := "/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/savingsPlans"
	if billingAccountName == "" {
		return nil, errors.New("parameter billingAccountName cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{billingAccountName}", url.PathEscape(billingAccountName))
	req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath))
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("api-version", "2024-04-01")
	if options != nil && options.Filter != nil {
		reqQP.Set("filter", *options.Filter)
	}
	if options != nil && options.OrderBy != nil {
		reqQP.Set("orderBy", *options.OrderBy)
	}
	if options != nil && options.RefreshSummary != nil {
		reqQP.Set("refreshSummary", *options.RefreshSummary)
	}
	if options != nil && options.SelectedState != nil {
		reqQP.Set("selectedState", *options.SelectedState)
	}
	if options != nil && options.Skiptoken != nil {
		reqQP.Set("skiptoken", strconv.FormatFloat(float64(*options.Skiptoken), 'f', -1, 32))
	}
	if options != nil && options.Take != nil {
		reqQP.Set("take", strconv.FormatFloat(float64(*options.Take), 'f', -1, 32))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header["Accept"] = []string{"application/json"}
	return req, nil
}

// listByBillingAccountHandleResponse handles the ListByBillingAccount response.
func (client *SavingsPlansClient) listByBillingAccountHandleResponse(resp *http.Response) (SavingsPlansClientListByBillingAccountResponse, error) {
	result := SavingsPlansClientListByBillingAccountResponse{}
	if err := runtime.UnmarshalAsJSON(resp, &result.SavingsPlanModelListResult); err != nil {
		return SavingsPlansClientListByBillingAccountResponse{}, err
	}
	return result, nil
}

// NewListBySavingsPlanOrderPager - List savings plans in an order by billing account.
//
// Generated from API version 2024-04-01
//   - billingAccountName - The ID that uniquely identifies a billing account.
//   - savingsPlanOrderID - Order ID of the savings plan
//   - options - SavingsPlansClientListBySavingsPlanOrderOptions contains the optional parameters for the SavingsPlansClient.NewListBySavingsPlanOrderPager
//     method.
func (client *SavingsPlansClient) NewListBySavingsPlanOrderPager(billingAccountName string, savingsPlanOrderID string, options *SavingsPlansClientListBySavingsPlanOrderOptions) *runtime.Pager[SavingsPlansClientListBySavingsPlanOrderResponse] {
	return runtime.NewPager(runtime.PagingHandler[SavingsPlansClientListBySavingsPlanOrderResponse]{
		More: func(page SavingsPlansClientListBySavingsPlanOrderResponse) bool {
			return page.NextLink != nil && len(*page.NextLink) > 0
		},
		Fetcher: func(ctx context.Context, page *SavingsPlansClientListBySavingsPlanOrderResponse) (SavingsPlansClientListBySavingsPlanOrderResponse, error) {
			ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "SavingsPlansClient.NewListBySavingsPlanOrderPager")
			nextLink := ""
			if page != nil {
				nextLink = *page.NextLink
			}
			resp, err := runtime.FetcherForNextLink(ctx, client.internal.Pipeline(), nextLink, func(ctx context.Context) (*policy.Request, error) {
				return client.listBySavingsPlanOrderCreateRequest(ctx, billingAccountName, savingsPlanOrderID, options)
			}, nil)
			if err != nil {
				return SavingsPlansClientListBySavingsPlanOrderResponse{}, err
			}
			return client.listBySavingsPlanOrderHandleResponse(resp)
		},
		Tracer: client.internal.Tracer(),
	})
}

// listBySavingsPlanOrderCreateRequest creates the ListBySavingsPlanOrder request.
func (client *SavingsPlansClient) listBySavingsPlanOrderCreateRequest(ctx context.Context, billingAccountName string, savingsPlanOrderID string, options *SavingsPlansClientListBySavingsPlanOrderOptions) (*policy.Request, error) {
	urlPath := "/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/savingsPlanOrders/{savingsPlanOrderId}/savingsPlans"
	if billingAccountName == "" {
		return nil, errors.New("parameter billingAccountName cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{billingAccountName}", url.PathEscape(billingAccountName))
	if savingsPlanOrderID == "" {
		return nil, errors.New("parameter savingsPlanOrderID cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{savingsPlanOrderId}", url.PathEscape(savingsPlanOrderID))
	req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath))
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("api-version", "2024-04-01")
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header["Accept"] = []string{"application/json"}
	return req, nil
}

// listBySavingsPlanOrderHandleResponse handles the ListBySavingsPlanOrder response.
func (client *SavingsPlansClient) listBySavingsPlanOrderHandleResponse(resp *http.Response) (SavingsPlansClientListBySavingsPlanOrderResponse, error) {
	result := SavingsPlansClientListBySavingsPlanOrderResponse{}
	if err := runtime.UnmarshalAsJSON(resp, &result.SavingsPlanModelList); err != nil {
		return SavingsPlansClientListBySavingsPlanOrderResponse{}, err
	}
	return result, nil
}

// BeginUpdateByBillingAccount - Update savings plan by billing account.
// If the operation fails it returns an *azcore.ResponseError type.
//
// Generated from API version 2024-04-01
//   - billingAccountName - The ID that uniquely identifies a billing account.
//   - savingsPlanOrderID - Order ID of the savings plan
//   - savingsPlanID - ID of the savings plan
//   - body - Request body for patching a savings plan order alias
//   - options - SavingsPlansClientBeginUpdateByBillingAccountOptions contains the optional parameters for the SavingsPlansClient.BeginUpdateByBillingAccount
//     method.
func (client *SavingsPlansClient) BeginUpdateByBillingAccount(ctx context.Context, billingAccountName string, savingsPlanOrderID string, savingsPlanID string, body SavingsPlanUpdateRequest, options *SavingsPlansClientBeginUpdateByBillingAccountOptions) (*runtime.Poller[SavingsPlansClientUpdateByBillingAccountResponse], error) {
	if options == nil || options.ResumeToken == "" {
		resp, err := client.updateByBillingAccount(ctx, billingAccountName, savingsPlanOrderID, savingsPlanID, body, options)
		if err != nil {
			return nil, err
		}
		poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[SavingsPlansClientUpdateByBillingAccountResponse]{
			FinalStateVia: runtime.FinalStateViaAzureAsyncOp,
			Tracer:        client.internal.Tracer(),
		})
		return poller, err
	} else {
		return runtime.NewPollerFromResumeToken(options.ResumeToken, client.internal.Pipeline(), &runtime.NewPollerFromResumeTokenOptions[SavingsPlansClientUpdateByBillingAccountResponse]{
			Tracer: client.internal.Tracer(),
		})
	}
}

// UpdateByBillingAccount - Update savings plan by billing account.
// If the operation fails it returns an *azcore.ResponseError type.
//
// Generated from API version 2024-04-01
func (client *SavingsPlansClient) updateByBillingAccount(ctx context.Context, billingAccountName string, savingsPlanOrderID string, savingsPlanID string, body SavingsPlanUpdateRequest, options *SavingsPlansClientBeginUpdateByBillingAccountOptions) (*http.Response, error) {
	var err error
	const operationName = "SavingsPlansClient.BeginUpdateByBillingAccount"
	ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, operationName)
	ctx, endSpan := runtime.StartSpan(ctx, operationName, client.internal.Tracer(), nil)
	defer func() { endSpan(err) }()
	req, err := client.updateByBillingAccountCreateRequest(ctx, billingAccountName, savingsPlanOrderID, savingsPlanID, body, options)
	if err != nil {
		return nil, err
	}
	httpResp, err := client.internal.Pipeline().Do(req)
	if err != nil {
		return nil, err
	}
	if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusAccepted) {
		err = runtime.NewResponseError(httpResp)
		return nil, err
	}
	return httpResp, nil
}

// updateByBillingAccountCreateRequest creates the UpdateByBillingAccount request.
func (client *SavingsPlansClient) updateByBillingAccountCreateRequest(ctx context.Context, billingAccountName string, savingsPlanOrderID string, savingsPlanID string, body SavingsPlanUpdateRequest, options *SavingsPlansClientBeginUpdateByBillingAccountOptions) (*policy.Request, error) {
	urlPath := "/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/savingsPlanOrders/{savingsPlanOrderId}/savingsPlans/{savingsPlanId}"
	if billingAccountName == "" {
		return nil, errors.New("parameter billingAccountName cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{billingAccountName}", url.PathEscape(billingAccountName))
	if savingsPlanOrderID == "" {
		return nil, errors.New("parameter savingsPlanOrderID cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{savingsPlanOrderId}", url.PathEscape(savingsPlanOrderID))
	if savingsPlanID == "" {
		return nil, errors.New("parameter savingsPlanID cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{savingsPlanId}", url.PathEscape(savingsPlanID))
	req, err := runtime.NewRequest(ctx, http.MethodPatch, runtime.JoinPaths(client.internal.Endpoint(), urlPath))
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("api-version", "2024-04-01")
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header["Accept"] = []string{"application/json"}
	if err := runtime.MarshalAsJSON(req, body); err != nil {
		return nil, err
	}
	return req, nil
}

// ValidateUpdateByBillingAccount - Validate savings plan patch by billing account.
// If the operation fails it returns an *azcore.ResponseError type.
//
// Generated from API version 2024-04-01
//   - billingAccountName - The ID that uniquely identifies a billing account.
//   - savingsPlanOrderID - Order ID of the savings plan
//   - savingsPlanID - ID of the savings plan
//   - body - Request body for patching a savings plan order alias
//   - options - SavingsPlansClientValidateUpdateByBillingAccountOptions contains the optional parameters for the SavingsPlansClient.ValidateUpdateByBillingAccount
//     method.
func (client *SavingsPlansClient) ValidateUpdateByBillingAccount(ctx context.Context, billingAccountName string, savingsPlanOrderID string, savingsPlanID string, body SavingsPlanUpdateValidateRequest, options *SavingsPlansClientValidateUpdateByBillingAccountOptions) (SavingsPlansClientValidateUpdateByBillingAccountResponse, error) {
	var err error
	const operationName = "SavingsPlansClient.ValidateUpdateByBillingAccount"
	ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, operationName)
	ctx, endSpan := runtime.StartSpan(ctx, operationName, client.internal.Tracer(), nil)
	defer func() { endSpan(err) }()
	req, err := client.validateUpdateByBillingAccountCreateRequest(ctx, billingAccountName, savingsPlanOrderID, savingsPlanID, body, options)
	if err != nil {
		return SavingsPlansClientValidateUpdateByBillingAccountResponse{}, err
	}
	httpResp, err := client.internal.Pipeline().Do(req)
	if err != nil {
		return SavingsPlansClientValidateUpdateByBillingAccountResponse{}, err
	}
	if !runtime.HasStatusCode(httpResp, http.StatusOK) {
		err = runtime.NewResponseError(httpResp)
		return SavingsPlansClientValidateUpdateByBillingAccountResponse{}, err
	}
	resp, err := client.validateUpdateByBillingAccountHandleResponse(httpResp)
	return resp, err
}

// validateUpdateByBillingAccountCreateRequest creates the ValidateUpdateByBillingAccount request.
func (client *SavingsPlansClient) validateUpdateByBillingAccountCreateRequest(ctx context.Context, billingAccountName string, savingsPlanOrderID string, savingsPlanID string, body SavingsPlanUpdateValidateRequest, options *SavingsPlansClientValidateUpdateByBillingAccountOptions) (*policy.Request, error) {
	urlPath := "/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/savingsPlanOrders/{savingsPlanOrderId}/savingsPlans/{savingsPlanId}/validate"
	if billingAccountName == "" {
		return nil, errors.New("parameter billingAccountName cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{billingAccountName}", url.PathEscape(billingAccountName))
	if savingsPlanOrderID == "" {
		return nil, errors.New("parameter savingsPlanOrderID cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{savingsPlanOrderId}", url.PathEscape(savingsPlanOrderID))
	if savingsPlanID == "" {
		return nil, errors.New("parameter savingsPlanID cannot be empty")
	}
	urlPath = strings.ReplaceAll(urlPath, "{savingsPlanId}", url.PathEscape(savingsPlanID))
	req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath))
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("api-version", "2024-04-01")
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header["Accept"] = []string{"application/json"}
	if err := runtime.MarshalAsJSON(req, body); err != nil {
		return nil, err
	}
	return req, nil
}

// validateUpdateByBillingAccountHandleResponse handles the ValidateUpdateByBillingAccount response.
func (client *SavingsPlansClient) validateUpdateByBillingAccountHandleResponse(resp *http.Response) (SavingsPlansClientValidateUpdateByBillingAccountResponse, error) {
	result := SavingsPlansClientValidateUpdateByBillingAccountResponse{}
	if err := runtime.UnmarshalAsJSON(resp, &result.SavingsPlanValidateResponse); err != nil {
		return SavingsPlansClientValidateUpdateByBillingAccountResponse{}, err
	}
	return result, nil
}
