package agent

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/service/approvalapp"
	"github.com/tidbcloud/AgentTeam/internal/service/role/execution"
	storeagent "github.com/tidbcloud/AgentTeam/internal/store/agent"
	"github.com/tidbcloud/AgentTeam/internal/store/app"
	"github.com/tidbcloud/AgentTeam/internal/store/approval"
	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

type fakeRoleManagers struct {
	principal execution.AgentPrincipal
	manager   execution.Manager
}

func (fake *fakeRoleManagers) ResolveManager(_ context.Context, principal execution.AgentPrincipal) (execution.Manager, error) {
	fake.principal = principal
	return fake.manager, nil
}

type fakeRoleReads struct {
	principal execution.RoleReadPrincipal
	listInput execution.RoleListInput
	getID     string
	list      execution.RoleListResult
	detail    execution.RoleDetail
}

func (fake *fakeRoleReads) List(_ context.Context, principal execution.RoleReadPrincipal, input execution.RoleListInput) (execution.RoleListResult, error) {
	fake.principal, fake.listInput = principal, input
	return fake.list, nil
}

func (fake *fakeRoleReads) Get(_ context.Context, principal execution.RoleReadPrincipal, roleID string) (execution.RoleDetail, error) {
	fake.principal, fake.getID = principal, roleID
	return fake.detail, nil
}

type fakeRoleRequests struct {
	command execution.RequestGetCommand
	result  execution.RequestResult
}

func (fake *fakeRoleRequests) RequestGet(_ context.Context, command execution.RequestGetCommand) (execution.RequestResult, error) {
	fake.command = command
	return fake.result, nil
}

type fakeRoleApprovals struct {
	requestType      string
	command          approvalapp.SubmitCommand
	result           approvalapp.SubmitResult
	results          []approvalapp.SubmitResult
	submitErr        error
	submitted        int
	presentErrors    []error
	presentedResults []approvalapp.SubmitResult
}

func (fake *fakeRoleApprovals) SubmitRequest(_ context.Context, requestType string, command approvalapp.SubmitCommand) (approvalapp.SubmitResult, error) {
	fake.requestType, fake.command = requestType, command
	if fake.submitErr != nil {
		fake.submitted++
		return approvalapp.SubmitResult{}, fake.submitErr
	}
	if fake.submitted < len(fake.results) {
		result := fake.results[fake.submitted]
		fake.submitted++
		return result, nil
	}
	fake.submitted++
	return fake.result, nil
}

func (fake *fakeRoleApprovals) PresentPending(_ context.Context, result approvalapp.SubmitResult) (app.AppNotificationResult, error) {
	index := len(fake.presentedResults)
	fake.presentedResults = append(fake.presentedResults, result)
	if index < len(fake.presentErrors) {
		return app.AppNotificationResult{}, fake.presentErrors[index]
	}
	return app.AppNotificationResult{}, nil
}

func agentRoleTestRouter(
	managers RoleManagerResolver,
	reads RoleReadRuntime,
	requests RoleRequestRuntime,
	approvals ApprovalRuntime,
) *gin.Engine {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	RegisterRoutes(router, Dependencies{
		Auth: fakeAgentAuthenticator{agent: storeagent.AuthenticatedAgent{
			AgentID: "agt_0000000000test", WorkspaceID: "wsp_test",
			MemberID: "00000000test", MachineID: "mac_test",
		}},
		RoleManagers: managers, RoleReads: reads,
		RoleRequests: requests, ApprovalSubjects: approvals,
	})
	return router
}

func TestAgentRoleRoutesAreCompleteAndNeverMountedOnDeprecatedRuntime(t *testing.T) {
	router := agentRoleTestRouter(
		&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, &fakeRoleApprovals{},
	)
	routes := map[string]bool{}
	for _, route := range router.Routes() {
		routes[route.Method+" "+route.Path] = true
	}
	base := "/api/v1/workspaces/:workspaceId/agents/:agentId/runtime/roles"
	for _, route := range []string{
		http.MethodGet + " " + base,
		http.MethodPost + " " + base + "/get",
		http.MethodPost + " " + base + "/request-get",
		http.MethodPost + " " + base + "/create",
		http.MethodPost + " " + base + "/update",
		http.MethodPost + " " + base + "/delete",
		http.MethodPost + " " + base + "/apply",
	} {
		require.True(t, routes[route], route)
	}
	for route := range routes {
		require.False(t, route == http.MethodGet+" /internal/agent/:agentId/roles" ||
			route == http.MethodPost+" /internal/agent/:agentId/roles/get" ||
			route == http.MethodPost+" /internal/agent/:agentId/roles/request-get" ||
			route == http.MethodPost+" /internal/agent/:agentId/roles/create" ||
			route == http.MethodPost+" /internal/agent/:agentId/roles/update" ||
			route == http.MethodPost+" /internal/agent/:agentId/roles/delete" ||
			route == http.MethodPost+" /internal/agent/:agentId/roles/apply",
			"Role routes must not extend the deprecated runtime: %s", route)
	}
}

func TestAgentRoleRoutesRequireCompleteDependencies(t *testing.T) {
	for name, dependencies := range map[string]Dependencies{
		"manager": {
			RoleReads: &fakeRoleReads{}, RoleRequests: &fakeRoleRequests{},
			ApprovalSubjects: &fakeRoleApprovals{},
		},
		"reads": {
			RoleManagers: &fakeRoleManagers{}, RoleRequests: &fakeRoleRequests{},
			ApprovalSubjects: &fakeRoleApprovals{},
		},
		"requests": {
			RoleManagers: &fakeRoleManagers{}, RoleReads: &fakeRoleReads{},
			ApprovalSubjects: &fakeRoleApprovals{},
		},
		"approval subjects": {
			RoleManagers: &fakeRoleManagers{}, RoleReads: &fakeRoleReads{},
			RoleRequests: &fakeRoleRequests{},
		},
	} {
		t.Run(name, func(t *testing.T) {
			gin.SetMode(gin.TestMode)
			router := gin.New()
			dependencies.Auth = fakeAgentAuthenticator{agent: storeagent.AuthenticatedAgent{
				AgentID: "agt_0000000000test", WorkspaceID: "wsp_test",
			}}
			RegisterRoutes(router, dependencies)
			for _, route := range router.Routes() {
				require.NotContains(t, route.Path, "/roles")
			}
		})
	}
}

func TestAgentRoleReadsUseTrustedCurrentManagerAndMinimalProjection(t *testing.T) {
	managers := &fakeRoleManagers{manager: execution.Manager{
		UserID: "usr_0000000manager", MemberID: "00000manager",
	}}
	reads := &fakeRoleReads{
		list: execution.RoleListResult{
			Roles: []execution.RoleSummary{{
				RoleID: "role_1", Name: "Reviewer", Description: "Reviews",
				Visibility: "workspace", RoleVersionID: "rlv_1", CanManage: true,
			}},
			NextCursor: "3",
		},
		detail: execution.RoleDetail{
			RoleID: "role_1", Name: "Reviewer", Description: "Reviews",
			Definition: "Review changes", Visibility: "workspace",
			RoleVersionID: "rlv_1", CanManage: true,
		},
	}
	router := agentRoleTestRouter(managers, reads, &fakeRoleRequests{}, &fakeRoleApprovals{})

	list := agentTaskRequest(t, router, http.MethodGet, "/roles?view=all&q=review&limit=7&cursor=2", nil)
	requireRoleAgentImplemented(t, list)
	require.Equal(t, "usr_0000000manager", reads.principal.Subject)
	require.Equal(t, "wsp_test", reads.principal.WorkspaceID)
	require.Equal(t, execution.RoleListInput{
		View: "all", Query: "review", Limit: 7, Cursor: "2",
	}, reads.listInput)
	require.Equal(t, "agt_0000000000test", managers.principal.AgentID)
	require.JSONEq(t, `{"roles":[{"roleId":"role_1","name":"Reviewer","description":"Reviews","visibility":"workspace","roleVersionId":"rlv_1","canManage":true}],"nextCursor":"3"}`, list.Body.String())

	get := agentTaskRequest(t, router, http.MethodPost, "/roles/get", map[string]any{
		"roleId": "role_1",
	})
	requireRoleAgentImplemented(t, get)
	require.Equal(t, "role_1", reads.getID)
	require.JSONEq(t, `{"role":{"roleId":"role_1","name":"Reviewer","description":"Reviews","definition":"Review changes","visibility":"workspace","roleVersionId":"rlv_1","canManage":true}}`, get.Body.String())
}

func TestAgentRoleRequestGetUsesSameAgentReadOnlyProjection(t *testing.T) {
	requests := &fakeRoleRequests{result: execution.RequestResult{
		ApprovalID: "appr_1", ApplicantAgentID: "agt_0000000000test",
		RequestID: "req_1", Action: execution.ActionApply,
		Status: execution.RequestFailed, RoleID: "role_1",
		RoleVersionID: "rlv_1", AgentID: "agt_00000000target",
		FailureCode: "not_found", FailureMessage: "Role not found",
	}}
	router := agentRoleTestRouter(
		&fakeRoleManagers{}, &fakeRoleReads{}, requests, &fakeRoleApprovals{},
	)
	response := agentTaskRequest(t, router, http.MethodPost, "/roles/request-get", map[string]any{
		"requestId": "req_1",
	})
	requireRoleAgentImplemented(t, response)
	require.Equal(t, "agt_0000000000test", requests.command.Principal.AgentID)
	require.Equal(t, "wsp_test", requests.command.Principal.WorkspaceID)
	require.Equal(t, "00000000test", requests.command.Principal.MemberID)
	require.Equal(t, "mac_test", requests.command.Principal.MachineID)
	require.Equal(t, "req_1", requests.command.RequestID)
	require.JSONEq(t, `{
		"requestId":"req_1","action":"apply","status":"failed","approvalId":"appr_1",
		"roleId":"role_1","roleVersionId":"rlv_1","agentId":"agt_00000000target",
		"failure":{"code":"not_found","message":"Role not found"}
	}`, response.Body.String())
	require.NotContains(t, response.Body.String(), "payload")
	require.NotContains(t, response.Body.String(), "digest")
	require.NotContains(t, response.Body.String(), "fence")
	require.NotContains(t, response.Body.String(), "receipt")
}

func TestAgentRoleMutationsSubmitClosedProposalsWithTrustedPrincipal(t *testing.T) {
	empty := ""
	tests := []struct {
		name      string
		path      string
		requestID string
		body      map[string]any
		want      execution.RoleProposal
	}{
		{
			name: "create", path: "/roles/create", requestID: "req_create",
			body: map[string]any{
				"requestId": "req_create", "name": "Reviewer",
				"definition": "Review changes", "description": "Reviews",
			},
			want: execution.RoleCreateProposal{
				Name: "Reviewer", Definition: "Review changes", Description: "Reviews",
			},
		},
		{
			name: "update omitted description", path: "/roles/update", requestID: "req_update_omit",
			body: map[string]any{
				"requestId": "req_update_omit", "roleId": "role_1",
				"expectedRoleVersionId": "rlv_1", "name": "Reviewer",
			},
			want: execution.RoleUpdateProposal{
				RoleID: "role_1", ExpectedRoleVersionID: "rlv_1",
				Name: agentRoleStringPointer("Reviewer"), Description: nil,
			},
		},
		{
			name: "update explicit clear", path: "/roles/update", requestID: "req_update",
			body: map[string]any{
				"requestId": "req_update", "roleId": "role_1",
				"expectedRoleVersionId": "rlv_1", "description": "",
			},
			want: execution.RoleUpdateProposal{
				RoleID: "role_1", ExpectedRoleVersionID: "rlv_1", Description: &empty,
			},
		},
		{
			name: "delete", path: "/roles/delete", requestID: "req_delete",
			body: map[string]any{
				"requestId": "req_delete", "roleId": "role_1",
				"expectedRoleVersionId": "rlv_1",
			},
			want: execution.RoleDeleteProposal{
				RoleID: "role_1", ExpectedRoleVersionID: "rlv_1",
			},
		},
		{
			name: "apply", path: "/roles/apply", requestID: "req_apply",
			body: map[string]any{
				"requestId": "req_apply", "roleId": "role_1",
				"roleVersionId": "rlv_1", "agentId": "agt_00000000target",
			},
			want: execution.RoleApplyProposal{
				RoleID: "role_1", RoleVersionID: "rlv_1", AgentID: "agt_00000000target",
			},
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			approvals := &fakeRoleApprovals{result: approvalapp.SubmitResult{
				Instance: approval.Instance{ID: "appr_1", State: approval.StatePending},
				Created:  true,
				Value: execution.RequestResult{
					ApprovalID: "appr_1", Status: execution.RequestPending,
				},
			}}
			router := agentRoleTestRouter(
				&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, approvals,
			)
			response := agentRoleRequest(t, router, http.MethodPost, test.path, test.body, "corr_1")
			requireRoleAgentImplemented(t, response)
			require.Equal(t, execution.RequestType, approvals.requestType)
			require.Equal(t, "agent", approvals.command.Principal.ActorType)
			require.Equal(t, "wsp_test", approvals.command.Principal.WorkspaceID)
			require.Equal(t, "agt_0000000000test", approvals.command.Principal.PrincipalID)
			require.Equal(t, "00000000test", approvals.command.Principal.MemberID)
			require.Equal(t, "mac_test", approvals.command.Principal.MachineID)
			require.Equal(t, test.requestID, approvals.command.ClientRequestID)
			require.Equal(t, "corr_1", approvals.command.CorrelationID)
			require.Equal(t, test.want, approvals.command.Payload)
			require.Len(t, approvals.presentedResults, 1)
			require.JSONEq(t, `{"approvalId":"appr_1","status":"pending"}`, response.Body.String())
		})
	}
}

func TestAgentRolePendingReplayRepresentsAfterInitialPresentationFailure(t *testing.T) {
	pending := func(created bool) approvalapp.SubmitResult {
		return approvalapp.SubmitResult{
			Instance: approval.Instance{ID: "appr_1", State: approval.StatePending},
			Created:  created,
			Value: execution.RequestResult{
				ApprovalID: "appr_1", Status: execution.RequestPending,
			},
		}
	}
	approvals := &fakeRoleApprovals{
		results:       []approvalapp.SubmitResult{pending(true), pending(false)},
		presentErrors: []error{errors.New("pending notification unavailable")},
	}
	router := agentRoleTestRouter(
		&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, approvals,
	)
	body := map[string]any{
		"requestId": "req_create", "name": "Reviewer", "definition": "Review",
	}

	first := agentTaskRequest(t, router, http.MethodPost, "/roles/create", body)
	require.Equal(t, http.StatusInternalServerError, first.Code, first.Body.String())
	require.Len(t, approvals.presentedResults, 1)

	replayed := agentTaskRequest(t, router, http.MethodPost, "/roles/create", body)
	requireRoleAgentImplemented(t, replayed)
	require.JSONEq(t, `{"approvalId":"appr_1","status":"pending"}`, replayed.Body.String())
	require.Len(t, approvals.presentedResults, 2,
		"an exact pending replay must retry the stable pending-card presentation")
	require.Equal(t, "appr_1", approvals.presentedResults[0].Instance.ID)
	require.Equal(t, approvals.presentedResults[0].Instance.ID, approvals.presentedResults[1].Instance.ID)
	require.True(t, approvals.presentedResults[0].Created)
	require.False(t, approvals.presentedResults[1].Created)
}

func TestAgentRoleMutationResponseUsesPublicRequestStatusForReplay(t *testing.T) {
	tests := []struct {
		name          string
		approvalState string
		status        execution.RequestStatus
	}{
		{name: "pending created", approvalState: approval.StatePending, status: execution.RequestPending},
		{name: "processing replay", approvalState: approval.StateApproved, status: execution.RequestProcessing},
		{name: "succeeded replay", approvalState: approval.StateApproved, status: execution.RequestSucceeded},
		{name: "rejected replay", approvalState: approval.StateRejected, status: execution.RequestRejected},
		{name: "failed replay", approvalState: approval.StateApproved, status: execution.RequestFailed},
		{name: "cancelled replay", approvalState: approval.StateCancelled, status: execution.RequestCancelled},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			created := test.status == execution.RequestPending
			approvals := &fakeRoleApprovals{result: approvalapp.SubmitResult{
				Instance: approval.Instance{ID: "appr_1", State: test.approvalState},
				Created:  created,
				Value: execution.RequestResult{
					ApprovalID: "appr_1", Status: test.status,
				},
			}}
			response := agentTaskRequest(t, agentRoleTestRouter(
				&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, approvals,
			), http.MethodPost, "/roles/create", map[string]any{
				"requestId": "req_create", "name": "Reviewer", "definition": "Review",
			})
			requireRoleAgentImplemented(t, response)
			require.JSONEq(t, `{"approvalId":"appr_1","status":"`+string(test.status)+`"}`, response.Body.String())
			if created {
				require.Len(t, approvals.presentedResults, 1)
			} else {
				require.Empty(t, approvals.presentedResults)
			}
		})
	}
}

func TestAgentRoleMutationResponseFailsClosedOnInvalidSubjectValue(t *testing.T) {
	for name, value := range map[string]any{
		"wrong type": "processing",
		"wrong approval": execution.RequestResult{
			ApprovalID: "appr_other", Status: execution.RequestProcessing,
		},
		"invalid public status": execution.RequestResult{
			ApprovalID: "appr_1", Status: execution.RequestStatus(approval.StateApproved),
		},
	} {
		t.Run(name, func(t *testing.T) {
			approvals := &fakeRoleApprovals{result: approvalapp.SubmitResult{
				Instance: approval.Instance{ID: "appr_1", State: approval.StatePending},
				Created:  true, Value: value,
			}}
			response := agentTaskRequest(t, agentRoleTestRouter(
				&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, approvals,
			), http.MethodPost, "/roles/create", map[string]any{
				"requestId": "req_create", "name": "Reviewer", "definition": "Review",
			})
			require.Equal(t, http.StatusUnprocessableEntity, response.Code, response.Body.String())
			require.NotContains(t, response.Body.String(), approval.StateApproved)
			require.Empty(t, approvals.presentedResults)
		})
	}
}

func TestRoleAgentErrorClassifierMapsStableSecretFreeStatuses(t *testing.T) {
	tests := []struct {
		name   string
		err    error
		status int
		code   string
	}{
		{name: "bad input", err: storeerr.BadRequest("raw bad input secret"), status: http.StatusBadRequest, code: "role_invalid_request"},
		{name: "invariant", err: execution.ErrInvariant, status: http.StatusUnprocessableEntity, code: "role_invalid_request"},
		{name: "forbidden", err: execution.ErrForbidden, status: http.StatusForbidden, code: "role_forbidden"},
		{name: "not found", err: storeerr.NotFound("raw missing secret"), status: http.StatusNotFound, code: "role_not_found"},
		{name: "conflict", err: execution.ErrConflict, status: http.StatusConflict, code: "role_conflict"},
		{name: "unknown", err: errors.New("raw dependency secret"), status: http.StatusInternalServerError, code: "role_internal"},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			response, ok := roleAgentErrorClassifier(test.err)
			require.True(t, ok)
			require.Equal(t, test.status, response.Status)
			require.Equal(t, test.code, response.Code)
			require.NotContains(t, response.Message, "secret")
			require.NotContains(t, response.Message, test.err.Error())
		})
	}
}

func TestDeterministicAgentRoleMutationsMapDeterministicPreflightFailures(t *testing.T) {
	tests := []struct {
		name   string
		suffix string
		body   map[string]any
		err    error
		status int
		code   string
	}{
		{
			name: "update missing role", suffix: "/roles/update",
			body: map[string]any{
				"requestId": "req_update", "roleId": "role_missing",
				"expectedRoleVersionId": "rlv_1", "name": "Reviewer",
			},
			err:    &execution.ApplyError{Outcome: execution.ApplyNotFound},
			status: http.StatusNotFound, code: "role_not_found",
		},
		{
			name: "apply missing role", suffix: "/roles/apply",
			body: map[string]any{
				"requestId": "req_apply", "roleId": "role_missing",
				"roleVersionId": "rlv_1", "agentId": "agt_00000000target",
			},
			err:    &execution.ApplyError{Outcome: execution.ApplyNotFound},
			status: http.StatusNotFound, code: "role_not_found",
		},
		{
			name: "delete stale role version", suffix: "/roles/delete",
			body: map[string]any{
				"requestId": "req_delete", "roleId": "role_1",
				"expectedRoleVersionId": "rlv_stale",
			},
			err:    &execution.ApplyError{Outcome: execution.ApplyVersionConflict},
			status: http.StatusConflict, code: "role_conflict",
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			approvals := &fakeRoleApprovals{
				submitErr: fmt.Errorf("preflight failed: %w", tt.err),
			}

			response := agentTaskRequest(t, agentRoleTestRouter(
				&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, approvals,
			), http.MethodPost, tt.suffix, tt.body)

			require.Equal(t, tt.status, response.Code, response.Body.String())
			require.Contains(t, response.Body.String(), `"code":"`+tt.code+`"`)
			require.Equal(t, 1, approvals.submitted)
			require.Empty(t, approvals.presentedResults)
		})
	}
}

func agentRoleRequest(
	t *testing.T,
	router http.Handler,
	method, suffix string,
	body any,
	correlationID string,
) *httptest.ResponseRecorder {
	t.Helper()
	var encoded []byte
	var err error
	if body != nil {
		encoded, err = json.Marshal(body)
		require.NoError(t, err)
	}
	request := httptest.NewRequest(
		method,
		"/api/v1/workspaces/wsp_test/agents/agt_0000000000test/runtime"+suffix,
		bytes.NewReader(encoded),
	)
	setAgentAuthHeader(request)
	request.Header.Set("Content-Type", "application/json")
	request.Header.Set("X-Request-ID", correlationID)
	response := httptest.NewRecorder()
	router.ServeHTTP(response, request)
	return response
}

func TestAgentRoleReplayRepresentsPendingWithStableApproval(t *testing.T) {
	approvals := &fakeRoleApprovals{result: approvalapp.SubmitResult{
		Instance: approval.Instance{ID: "appr_1", State: approval.StatePending},
		Created:  false,
		Value: execution.RequestResult{
			ApprovalID: "appr_1", Status: execution.RequestPending,
		},
	}}
	response := agentTaskRequest(t, agentRoleTestRouter(
		&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, approvals,
	), http.MethodPost, "/roles/create", map[string]any{
		"requestId": "req_create", "name": "Reviewer", "definition": "Review",
	})
	requireRoleAgentImplemented(t, response)
	require.Len(t, approvals.presentedResults, 1)
	require.Equal(t, "appr_1", approvals.presentedResults[0].Instance.ID)
	require.False(t, approvals.presentedResults[0].Created)
}

func TestAgentRoleStrictBodyRejectsTrustedIdentityOverrides(t *testing.T) {
	response := agentTaskRequest(t, agentRoleTestRouter(
		&fakeRoleManagers{}, &fakeRoleReads{}, &fakeRoleRequests{}, &fakeRoleApprovals{},
	), http.MethodPost, "/roles/apply", map[string]any{
		"requestId": "req_apply", "roleId": "role_1", "roleVersionId": "rlv_1",
		"agentId": "agt_00000000target", "workspaceId": "wsp_other",
		"managerUserId": "usr_000000000other", "ownedAgentIds": []string{"agt_000000000other"},
	})
	require.Equal(t, http.StatusBadRequest, response.Code)
}

func requireRoleAgentImplemented(t *testing.T, response *httptest.ResponseRecorder) {
	t.Helper()
	require.Equal(t, http.StatusOK, response.Code, response.Body.String())
}

func agentRoleStringPointer(value string) *string {
	return &value
}
