// Code generated by Fern. DO NOT EDIT.

package authenticationmethods

import (
	context "context"
	fmt "fmt"
	management "github.com/auth0/go-auth0/v2/management"
	core "github.com/auth0/go-auth0/v2/management/core"
	internal "github.com/auth0/go-auth0/v2/management/internal"
	option "github.com/auth0/go-auth0/v2/management/option"
	http "net/http"
	strconv "strconv"
)

type Client struct {
	WithRawResponse *RawClient

	options *core.RequestOptions
	baseURL string
	caller  *internal.Caller
}

func NewClient(options *core.RequestOptions) *Client {
	return &Client{
		WithRawResponse: NewRawClient(options),
		options:         options,
		baseURL:         options.BaseURL,
		caller: internal.NewCaller(
			&internal.CallerParams{
				Client:      options.HTTPClient,
				MaxAttempts: options.MaxAttempts,
			},
		),
	}
}

// Retrieve detailed list of authentication methods associated with a specified user.
func (c *Client) List(
	ctx context.Context,
	// The ID of the user in question.
	id string,
	request *management.ListUserAuthenticationMethodsRequestParameters,
	opts ...option.RequestOption,
) (*core.Page[*management.UserAuthenticationMethod], error) {
	options := core.NewRequestOptions(opts...)
	baseURL := internal.ResolveBaseURL(
		options.BaseURL,
		c.baseURL,
		"https://%7BTENANT%7D.auth0.com/api/v2",
	)
	endpointURL := internal.EncodeURL(
		baseURL+"/users/%v/authentication-methods",
		id,
	)
	queryParams, err := internal.QueryValues(request)
	if err != nil {
		return nil, err
	}
	headers := internal.MergeHeaders(
		c.options.ToHeader(),
		options.ToHeader(),
	)
	prepareCall := func(pageRequest *internal.PageRequest[*int]) *internal.CallParams {
		if pageRequest.Cursor != nil {
			queryParams.Set("page", fmt.Sprintf("%v", *pageRequest.Cursor))
		}
		nextURL := endpointURL
		if len(queryParams) > 0 {
			nextURL += "?" + queryParams.Encode()
		}
		return &internal.CallParams{
			URL:             nextURL,
			Method:          http.MethodGet,
			Headers:         headers,
			MaxAttempts:     options.MaxAttempts,
			BodyProperties:  options.BodyProperties,
			QueryParameters: options.QueryParameters,
			Client:          options.HTTPClient,
			Response:        pageRequest.Response,
			ErrorDecoder:    internal.NewErrorDecoder(management.ErrorCodes),
		}
	}
	next := 1
	if queryParams.Has("page") {
		var err error
		if next, err = strconv.Atoi(queryParams.Get("page")); err != nil {
			return nil, err
		}
	}

	readPageResponse := func(response *management.ListUserAuthenticationMethodsOffsetPaginatedResponseContent) *internal.PageResponse[*int, *management.UserAuthenticationMethod] {
		next += 1
		results := response.Authenticators
		return &internal.PageResponse[*int, *management.UserAuthenticationMethod]{
			Next:    &next,
			Results: results,
		}
	}
	pager := internal.NewOffsetPager(
		c.caller,
		prepareCall,
		readPageResponse,
	)
	return pager.GetPage(ctx, &next)
}

// Create an authentication method. Authentication methods created via this endpoint will be auto confirmed and should already have verification completed.
func (c *Client) Create(
	ctx context.Context,
	// The ID of the user to whom the new authentication method will be assigned.
	id string,
	request *management.CreateUserAuthenticationMethodRequestContent,
	opts ...option.RequestOption,
) (*management.CreateUserAuthenticationMethodResponseContent, error) {
	response, err := c.WithRawResponse.Create(
		ctx,
		id,
		request,
		opts...,
	)
	if err != nil {
		return nil, err
	}
	return response.Body, nil
}

// Replace the specified user <a href="https://auth0.com/docs/secure/multi-factor-authentication/multi-factor-authentication-factors"> authentication methods</a> with supplied values.
//
//	<b>Note</b>: Authentication methods supplied through this action do not iterate on existing methods. Instead, any methods passed will overwrite the user&#8217s existing settings.
func (c *Client) Set(
	ctx context.Context,
	// The ID of the user in question.
	id string,
	request management.SetUserAuthenticationMethodsRequestContent,
	opts ...option.RequestOption,
) ([]*management.SetUserAuthenticationMethodResponseContent, error) {
	response, err := c.WithRawResponse.Set(
		ctx,
		id,
		request,
		opts...,
	)
	if err != nil {
		return nil, err
	}
	return response.Body, nil
}

// Remove all authentication methods (i.e., enrolled MFA factors) from the specified user account. This action cannot be undone.
func (c *Client) DeleteAll(
	ctx context.Context,
	// The ID of the user in question.
	id string,
	opts ...option.RequestOption,
) error {
	_, err := c.WithRawResponse.DeleteAll(
		ctx,
		id,
		opts...,
	)
	if err != nil {
		return err
	}
	return nil
}

func (c *Client) Get(
	ctx context.Context,
	// The ID of the user in question.
	id string,
	// The ID of the authentication methods in question.
	authenticationMethodID string,
	opts ...option.RequestOption,
) (*management.GetUserAuthenticationMethodResponseContent, error) {
	response, err := c.WithRawResponse.Get(
		ctx,
		id,
		authenticationMethodID,
		opts...,
	)
	if err != nil {
		return nil, err
	}
	return response.Body, nil
}

// Remove the authentication method with the given ID from the specified user. For more information, review <a href="https://auth0.com/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authentication-methods-with-management-api">Manage Authentication Methods with Management API</a>.
func (c *Client) Delete(
	ctx context.Context,
	// The ID of the user in question.
	id string,
	// The ID of the authentication method to delete.
	authenticationMethodID string,
	opts ...option.RequestOption,
) error {
	_, err := c.WithRawResponse.Delete(
		ctx,
		id,
		authenticationMethodID,
		opts...,
	)
	if err != nil {
		return err
	}
	return nil
}

// Modify the authentication method with the given ID from the specified user. For more information, review <a href="https://auth0.com/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authentication-methods-with-management-api">Manage Authentication Methods with Management API</a>.
func (c *Client) Update(
	ctx context.Context,
	// The ID of the user in question.
	id string,
	// The ID of the authentication method to update.
	authenticationMethodID string,
	request *management.UpdateUserAuthenticationMethodRequestContent,
	opts ...option.RequestOption,
) (*management.UpdateUserAuthenticationMethodResponseContent, error) {
	response, err := c.WithRawResponse.Update(
		ctx,
		id,
		authenticationMethodID,
		request,
		opts...,
	)
	if err != nil {
		return nil, err
	}
	return response.Body, nil
}
