// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.

package {{(.TrimPrefix "account").SnakeName}}

import (
    "github.com/databricks/cli/libs/cmdio"
    "github.com/databricks/cli/libs/flags"
	"github.com/databricks/cli/libs/diag"
	"github.com/databricks/cli/cmd/root"
	"github.com/databricks/databricks-sdk-go/service/{{.Package.Name}}"
	"github.com/spf13/cobra"

	{{range .Subservices -}}
	{{.SnakeName}} "github.com/databricks/cli/cmd/{{ if .ParentService.IsAccounts }}account{{ else }}workspace{{ end }}/{{.KebabName}}"
	{{end}}
)

{{ $excludes :=
	list
		"command-execution"
		"statement-execution"
		"dbfs"
		"dbsql-permissions"
		"account-access-control-proxy"
		"files"
		"serving-endpoints-data-plane"
}}

{{if not (in $excludes .KebabName) }}
	{{template "service" .}}
{{else}}
	{{skipThisFile}}
{{end}}

{{define "printArray" -}}
{{if le (len .) 5 -}}
	[{{range $index, $element := .}}{{if ne $index 0}}, {{end}}{{$element.Name}}{{end}}]
{{- else -}}[{{range $index, $element := .}}
  {{$element.Name}},{{end}}
]{{end}}{{end}}

{{define "service"}}
{{- $excludeMethods := list "put-secret" -}}
{{- $hideService := .IsPrivatePreview }}

// Slice with functions to override default command behavior.
// Functions can be added from the `init()` function in manually curated files in this directory.
var cmdOverrides []func(*cobra.Command)

func New() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "{{(.TrimPrefix "account").KebabName}}",
		{{- if .Description }}
		Short: `{{.Summary | without "`"}}`,
		Long: `{{.Comment  "  " 80 | without "`"}}`,
		{{- end }}
		{{- if not .HasParent }}
		GroupID: "{{ .Package.Name }}",
		Annotations: map[string]string{
			"package": "{{ .Package.Name }}",
		},
		{{- end }}
		{{- if $hideService }}

		// This service is being previewed; hide from help output.
		Hidden: true,
		{{- end }}
	}

	{{ if gt (len .Methods) 0 -}}
	// Add methods
	{{- range .Methods}}
		{{- if in $excludeMethods .KebabName }}
			{{- continue}}
		{{- end}}
		cmd.AddCommand(new{{.PascalName}}())
	{{- end}}
	{{- end}}

	{{ if .HasSubservices }}
	// Add subservices
	{{- range .Subservices}}
	cmd.AddCommand({{.SnakeName}}.New())
	{{- end}}
	{{- end}}

	// Apply optional overrides to this command.
	for _, fn := range cmdOverrides {
		fn(cmd)
	}

	return cmd
}

{{- $serviceName := .KebabName -}}
{{range .Methods}}

{{if in $excludeMethods .KebabName }}
	{{continue}}
{{end}}
// start {{.KebabName}} command

// Slice with functions to override default command behavior.
// Functions can be added from the `init()` function in manually curated files in this directory.
var {{.CamelName}}Overrides []func(
	*cobra.Command,
	{{- if .Request }}
	*{{.Service.Package.Name}}.{{.Request.PascalName}},
	{{- end }}
)

{{- $excludeFromJson := list "http-request"}}

func new{{.PascalName}}() *cobra.Command {
	cmd := &cobra.Command{}

	{{- $canUseJson := and .CanUseJson (not (in $excludeFromJson .KebabName )) -}}
	{{- if .Request}}

	var {{.CamelName}}Req {{.Service.Package.Name}}.{{.Request.PascalName}}
	{{- if .RequestBodyField }}
	{{.CamelName}}Req.{{.RequestBodyField.PascalName}} = &{{.Service.Package.Name}}.{{.RequestBodyField.Entity.PascalName}}{}
	{{- end }}
	{{- if $canUseJson}}
	var {{.CamelName}}Json flags.JsonFlag
	{{- end}}
	{{- end}}

	{{if .Wait}}var {{.CamelName}}SkipWait bool
	var {{.CamelName}}Timeout time.Duration{{end}}

	{{if .Wait}}
	cmd.Flags().BoolVar(&{{.CamelName}}SkipWait, "no-wait", {{.CamelName}}SkipWait, `do not wait to reach {{range $i, $e := .Wait.Success}}{{if $i}} or {{end}}{{.Content}}{{end}} state`)
	cmd.Flags().DurationVar(&{{.CamelName}}Timeout, "timeout", {{.Wait.Timeout}}*time.Minute, `maximum amount of time to reach {{range $i, $e := .Wait.Success}}{{if $i}} or {{end}}{{.Content}}{{end}} state`)
	{{end -}}
	{{- $request := .Request -}}
	{{- if .RequestBodyField -}}
	{{- $request = .RequestBodyField.Entity -}}
	{{- end -}}
    {{if $request }}// TODO: short flags
	{{- if $canUseJson}}
	cmd.Flags().Var(&{{.CamelName}}Json, "json", `either inline JSON string or @path/to/file.json with request body`)
	{{- end}}
    {{$method := .}}
	{{ if not .IsJsonOnly }}
	{{range .AllFields -}}
		{{- if not .Required -}}
			{{if .Entity.IsObject}}{{if not (eq . $method.RequestBodyField) }}// TODO: complex arg: {{.Name}}{{end}}
			{{else if .Entity.IsAny }}// TODO: any: {{.Name}}
			{{else if .Entity.ArrayValue }}// TODO: array: {{.Name}}
			{{else if .Entity.MapValue }}// TODO: map via StringToStringVar: {{.Name}}
			{{else if .Entity.IsEmpty }}// TODO: output-only field
			{{else if .Entity.IsComputed -}}
			{{else if .IsOutputOnly -}}
			{{else if .Entity.Enum }}cmd.Flags().Var(&{{- template "request-body-obj" (dict "Method" $method "Field" .)}}, "{{.KebabName}}", `{{.Summary | without "`" | trimSuffix "."}}. Supported values: {{template "printArray" .Entity.Enum}}`)
			{{else}}cmd.Flags().{{template "arg-type" .Entity}}(&{{- template "request-body-obj" (dict "Method" $method "Field" .)}}, "{{.KebabName}}", {{- template "request-body-obj" (dict "Method" $method "Field" .)}}, `{{.Summary | without "`"}}`)
			{{end}}
		{{- end -}}
	{{- end}}
	{{- end}}
	{{end}}

	{{- $excludeFromPrompts := list
		"workspace get-status"
		"provider-exchanges get"
		"provider-exchanges delete"
		"provider-exchanges delete-listing-from-exchange"
		"provider-exchanges list-exchanges-for-listing"
		"provider-exchanges list-listings-for-exchange"
		"storage-credentials get"
		-}}
	{{- $fullCommandName := (print $serviceName " " .KebabName) -}}
	{{- $noPrompt := or .IsCrudCreate (in $excludeFromPrompts $fullCommandName) }}

	{{- $hasPosArgs := .HasRequiredPositionalArguments -}}
	{{- $hasSinglePosArg := and $hasPosArgs (eq 1 (len $request.RequiredFields)) -}}
	{{- $serviceHasNamedIdMap := and (and .Service.List .Service.List.NamedIdMap) (not (eq .PascalName "List")) -}}
	{{- $hasIdPrompt := and (not $noPrompt) (and $hasSinglePosArg $serviceHasNamedIdMap) -}}
	{{- $wait := and .Wait (and (not .IsCrudRead) (not (eq .SnakeName "get_run"))) -}}
	{{- $hasRequiredArgs :=  and (not $hasIdPrompt) $hasPosArgs -}}
	{{- $hasSingleRequiredRequestBodyFieldWithPrompt := and (and $hasIdPrompt $request) (eq 1 (len $request.RequiredRequestBodyFields))  -}}
	{{- $onlyPathArgsRequiredAsPositionalArguments := and $request (eq (len .RequiredPositionalArguments) (len $request.RequiredPathFields)) -}}
	{{- $hasDifferentArgsWithJsonFlag := and (not $onlyPathArgsRequiredAsPositionalArguments) (and $canUseJson (or $request.HasRequiredRequestBodyFields )) -}}
	{{- $hasCustomArgHandler := or $hasRequiredArgs $hasDifferentArgsWithJsonFlag -}}

	{{- $atleastOneArgumentWithDescription := false -}}
	{{- if $hasPosArgs -}}
		{{- range .RequiredPositionalArguments -}}
			{{- if .HasComment -}}
				{{- $atleastOneArgumentWithDescription = true -}}
				{{- break -}}
			{{- end -}}
		{{- end -}}
	{{- end -}}

	cmd.Use = "{{.KebabName}}{{if $hasPosArgs}}{{range .RequiredPositionalArguments}} {{.ConstantName}}{{end}}{{end}}"
	{{- if .Description }}
	cmd.Short = `{{.Summary | without "`"}}`
	cmd.Long = `{{.Comment  "  " 80 | without "`"}}
	{{- if $atleastOneArgumentWithDescription }}

  Arguments:
    {{- range .RequiredPositionalArguments }}
    {{ .ConstantName }}: {{.Comment "      " 80 | without "`"}}
    {{- end -}}
    {{- end -}}
	`
	{{- end }}
	{{/* Don't hide commands if the service itself is already hidden. */}}
	{{- if and (not $hideService) .IsPrivatePreview }}

	// This command is being previewed; hide from help output.
	cmd.Hidden = true
	{{- end }}

	cmd.Annotations = make(map[string]string)
	{{ if $hasCustomArgHandler }}
	cmd.Args = func(cmd *cobra.Command, args []string) error {
		{{- if $hasDifferentArgsWithJsonFlag }}
		if cmd.Flags().Changed("json") {
			err := root.ExactArgs({{len $request.RequiredPathFields}})(cmd, args)
			if err != nil {
			{{- if eq 0 (len $request.RequiredPathFields) }}
				return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide{{- range $index, $field := $request.RequiredFields}}{{if $index}},{{end}} '{{$field.Name}}'{{end}} in your JSON input")
			{{- else }}
				return fmt.Errorf("when --json flag is specified, provide only{{- range $index, $field := $request.RequiredPathFields}}{{if $index}},{{end}} {{$field.ConstantName}}{{end}} as positional arguments. Provide{{- range $index, $field := $request.RequiredRequestBodyFields}}{{if $index}},{{end}} '{{$field.Name}}'{{end}} in your JSON input")
			{{- end }}
			}
			return nil
		}
		{{- end }}
		{{- if $hasRequiredArgs }}
		check := root.ExactArgs({{len .RequiredPositionalArguments}})
		return check(cmd, args)
		{{- else}}
		return nil
		{{- end }}
	}
	{{ end }}
	cmd.PreRunE = root.Must{{if .Service.IsAccounts}}Account{{else}}Workspace{{end}}Client
	cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
		ctx := cmd.Context()
		{{if .Service.IsAccounts}}a := root.AccountClient(ctx){{else}}w := root.WorkspaceClient(ctx){{end}}
		{{- if .Request }}
			{{ if $canUseJson }}
			if cmd.Flags().Changed("json") {
					diags := {{.CamelName}}Json.Unmarshal(&{{.CamelName}}Req{{ if .RequestBodyField }}.{{.RequestBodyField.PascalName}}{{ end }})
					if diags.HasError() {
						return diags.Error()
					}
					if len(diags) > 0 {
						err := cmdio.RenderDiagnosticsToErrorOut(ctx, diags)
						if err != nil {
							return err
						}
					}
			}{{end}}{{ if .MustUseJson }}else {
				return fmt.Errorf("please provide command input in JSON format by specifying the --json flag")
			}{{- end}}
			{{- if $hasPosArgs }}
			{{- if and $canUseJson $hasSingleRequiredRequestBodyFieldWithPrompt }} else {
			{{- end}}
			{{- if $hasIdPrompt}}
				if len(args) == 0 {
					promptSpinner := cmdio.Spinner(ctx)
					promptSpinner <- "No{{range $request.RequiredFields}} {{.ConstantName}}{{end}} argument specified. Loading names for {{.Service.TitleName}} drop-down."
					names, err := {{if .Service.IsAccounts}}a{{else}}w{{end}}.{{(.Service.TrimPrefix "account").PascalName}}.{{.Service.List.NamedIdMap.PascalName}}(ctx{{if .Service.List.Request}}, {{.Service.Package.Name}}.{{.Service.List.Request.PascalName}}{}{{end}})
					close(promptSpinner)
					if err != nil {
						return fmt.Errorf("failed to load names for {{.Service.TitleName}} drop-down. Please manually specify required arguments. Original error: %w", err)
					}
					id, err := cmdio.Select(ctx, names, "{{range $request.RequiredFields}}{{.Summary | trimSuffix "."}}{{end}}")
					if err != nil {
						return err
					}
					args = append(args, id)
				}
				if len(args) != 1 {
					return fmt.Errorf("expected to have {{range $request.RequiredFields}}{{.Summary | trimSuffix "." | lower}}{{end}}")
				}
			{{- end -}}

			{{$method := .}}
			{{- range $arg, $field := .RequiredPositionalArguments}}
				{{- template "args-scan" (dict "Arg" $arg "Field" $field "Method" $method "HasIdPrompt" $hasIdPrompt "ExcludeFromJson" $excludeFromJson)}}
			{{- end -}}
			{{- if and $canUseJson $hasSingleRequiredRequestBodyFieldWithPrompt }}
			}
			{{- end}}

			{{- end}}
		{{end}}
		{{if $wait -}}
		wait, err := {{if .Service.IsAccounts}}a{{else}}w{{end}}.{{.Service.PascalName}}.{{.PascalName}}(ctx{{if .Request}}, {{.CamelName}}Req{{end}})
		if err != nil {
			return err
		}
		if {{.CamelName}}SkipWait {
			{{if not .Response.IsEmpty -}}
			return cmdio.Render(ctx, wait.Response)
			{{- else -}}
			return nil
			{{- end}}
		}
		spinner := cmdio.Spinner(ctx)
		info, err := wait.OnProgress(func(i *{{.Service.Package.Name}}.{{.Wait.Poll.Response.PascalName}}) {
			{{if .Wait.MessagePath -}}
			{{if .Wait.ComplexMessagePath -}}
			if i.{{.Wait.MessagePathHead.PascalName}} == nil {
				return
			}
			status := i{{range .Wait.StatusPath}}.{{.PascalName}}{{end}}
			statusMessage := fmt.Sprintf("current status: %s", status)
			if i.{{.Wait.MessagePathHead.PascalName}} != nil {
				statusMessage = i{{range .Wait.MessagePath}}.{{.PascalName}}{{end}}
			}
			{{- else -}}
			statusMessage := i{{range .Wait.MessagePath}}.{{.PascalName}}{{end}}
			{{- end}}
			{{- else -}}
			status := i{{range .Wait.StatusPath}}.{{.PascalName}}{{end}}
			statusMessage := fmt.Sprintf("current status: %s", status)
			{{- end}}
			spinner <- statusMessage
		}).GetWithTimeout({{.CamelName}}Timeout)
		close(spinner)
		if err != nil {
			return err
		}
		return cmdio.Render(ctx, info)
		{{- else -}}
		{{template "method-call" .}}
		{{end -}}
	}

	// Disable completions since they are not applicable.
	// Can be overridden by manual implementation in `override.go`.
	cmd.ValidArgsFunction = cobra.NoFileCompletions

	// Apply optional overrides to this command.
	for _, fn := range {{.CamelName}}Overrides {
		fn(cmd{{if .Request}}, &{{.CamelName}}Req{{end}})
	}

	return cmd
}

{{end}}
// end service {{.Name}}{{end}}

{{- define "method-call" -}}
		{{if not .Response.IsEmpty -}}
		  response{{ if not .Pagination}}, err{{end}} :=
		{{- else -}}
		  err =
		{{- end}}
		{{- if .Service.IsAccounts}}a{{else}}w{{end}}.
		{{- if .Service.HasParent }}
			{{- (.Service.ParentService.TrimPrefix "account").PascalName }}.
			{{- (.Service.TrimPrefix "account").PascalName}}().
		{{- else}}
			{{- (.Service.TrimPrefix "account").PascalName}}.
		{{- end}}
		{{- .PascalName}}(ctx{{if .Request}}, {{.CamelName}}Req{{end}})
		{{- if not (and .Response .Pagination) }}
		if err != nil {
			return err
		}
		{{- end}}
		{{ if not .Response.IsEmpty -}}
			{{- if .IsResponseByteStream -}}
			defer response.{{.ResponseBodyField.PascalName}}.Close()
			return cmdio.Render{{ if .Pagination}}Iterator{{end}}(ctx, response.{{.ResponseBodyField.PascalName}})
			{{- else -}}
			return cmdio.Render{{ if .Pagination}}Iterator{{end}}(ctx, response)
			{{- end -}}
		{{ else -}}
		return nil
		{{- end -}}
{{- end -}}

{{- define "arg-type" -}}
	{{- if .IsString}}StringVar
	{{- else if .IsBool}}BoolVar
	{{- else if .IsInt64}}Int64Var
	{{- else if .IsFloat64}}Float64Var
	{{- else if .IsInt}}IntVar
	{{- else if .Enum }}StringVar
	{{- else}}/* NOT PRIMITIVE */
	{{- end -}}
{{- end -}}

{{- define "args-scan" -}}
	{{- $field := .Field -}}
	{{- $method := .Method -}}
	{{- $arg := .Arg -}}
	{{- $hasIdPrompt := .HasIdPrompt -}}
	{{ $canUseJson := and $method.CanUseJson (not (in .ExcludeFromJson $method.KebabName)) }}
	{{- $optionalIfJsonIsUsed := and (not $hasIdPrompt) (and $field.IsRequestBodyField $canUseJson) }}
	{{- if $optionalIfJsonIsUsed  }}
	if !cmd.Flags().Changed("json") {
	{{- end }}
	{{if not $field.Entity.IsString -}}
	_, err = fmt.Sscan(args[{{$arg}}], &{{- template "request-body-obj" (dict "Method" $method "Field" $field)}})
	if err != nil {
		return fmt.Errorf("invalid {{$field.ConstantName}}: %s", args[{{$arg}}])
	}{{else -}}
	{{- template "request-body-obj" (dict "Method" $method "Field" $field)}} = args[{{$arg}}]
	{{- end -}}
	{{- if $optionalIfJsonIsUsed  }}
	}
	{{- end }}
{{- end -}}

{{- define "request-body-obj" -}}
	{{- $method := .Method -}}
	{{- $field := .Field -}}
	{{$method.CamelName}}Req{{ if (and $method.RequestBodyField (and (not $field.IsPath) (not $field.IsQuery))) }}.{{$method.RequestBodyField.PascalName}}{{end}}.{{$field.PascalName}}
{{- end -}}