// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cmd

import (
	"context"
	"flag"
	"fmt"
	"regexp"
	"slices"
	"strings"

	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/tool"
)

// codeaction implements the codeaction verb for gopls.
type codeaction struct {
	EditFlags
	Kind  string `flag:"kind" help:"comma-separated list of code action kinds to filter"`
	Title string `flag:"title" help:"regular expression to match title"`
	Exec  bool   `flag:"exec" help:"execute the first matching code action"`

	app *Application
}

func (cmd *codeaction) Name() string      { return "codeaction" }
func (cmd *codeaction) Parent() string    { return cmd.app.Name() }
func (cmd *codeaction) Usage() string     { return "[codeaction-flags] filename[:line[:col]]" }
func (cmd *codeaction) ShortHelp() string { return "list or execute code actions" }
func (cmd *codeaction) DetailedHelp(f *flag.FlagSet) {
	fmt.Fprintf(f.Output(), `

The codeaction command lists or executes code actions for the
specified file or range of a file. Each code action contains
either an edit to be directly applied to the file, or a command
to be executed by the server, which may have an effect such as:
- requesting that the client apply an edit;
- changing the state of the server; or
- requesting that the client open a document.

The -kind and -title flags filter the list of actions.

The -kind flag specifies a comma-separated list of LSP CodeAction kinds.
Only actions of these kinds will be requested from the server.
Valid kinds include:

	gopls.doc.features
	quickfix
	refactor
	refactor.extract
	refactor.extract.constant
	refactor.extract.function
	refactor.extract.method
	refactor.extract.toNewFile
	refactor.extract.variable
	refactor.inline
	refactor.inline.call
	refactor.rewrite
	refactor.rewrite.changeQuote
	refactor.rewrite.fillStruct
	refactor.rewrite.fillSwitch
	refactor.rewrite.invertIf
	refactor.rewrite.joinLines
	refactor.rewrite.removeUnusedParam
	refactor.rewrite.splitLines
	source
	source.assembly
	source.doc
	source.fixAll
	source.freesymbols
	source.organizeImports
	source.test

Kinds are hierarchical, so "refactor" includes "refactor.inline".
(Note: actions of kind "source.test" are not returned unless explicitly
requested.)

The -title flag specifies a regular expression that must match the
action's title. (Ideally kinds would be specific enough that this
isn't necessary; we really need to subdivide refactor.rewrite; see
gopls/internal/settings/codeactionkind.go.)

The -exec flag causes the first matching code action to be executed.
Without the flag, the matching actions are merely listed.

It is not currently possible to execute more than one action,
as that requires a way to detect and resolve conflicts.
TODO(adonovan): support it when golang/go#67049 is resolved.

If executing an action causes the server to send a patch to the
client, the usual -write, -preserve, -diff, and -list flags govern how
the client deals with the patch.

Example: execute the first "quick fix" in the specified file and show the diff:

	$ gopls codeaction -kind=quickfix -exec -diff ./gopls/main.go

codeaction-flags:
`)
	printFlagDefaults(f)
}

func (cmd *codeaction) Run(ctx context.Context, args ...string) error {
	if len(args) < 1 {
		return tool.CommandLineErrorf("codeaction expects at least 1 argument")
	}
	cmd.app.editFlags = &cmd.EditFlags
	cli, _, err := cmd.app.connect(ctx)
	if err != nil {
		return err
	}
	defer cli.terminate(ctx)

	from := parseSpan(args[0])
	uri := from.URI()
	file, err := cli.openFile(ctx, uri)
	if err != nil {
		return err
	}
	rng, err := file.spanRange(from)
	if err != nil {
		return err
	}

	titleRE, err := regexp.Compile(cmd.Title)
	if err != nil {
		return err
	}

	// Get diagnostics, as they may encode various lazy code actions.
	if err := diagnoseFiles(ctx, cli.server, []protocol.DocumentURI{uri}); err != nil {
		return err
	}
	file.diagnosticsMu.Lock()
	diagnostics := slices.Clone(file.diagnostics)
	file.diagnosticsMu.Unlock()

	// Request code actions of the desired kinds.
	var kinds []protocol.CodeActionKind
	if cmd.Kind != "" {
		for kind := range strings.SplitSeq(cmd.Kind, ",") {
			kinds = append(kinds, protocol.CodeActionKind(kind))
		}
	} else {
		kinds = append(kinds, protocol.Empty) // => all
	}
	actions, err := cli.server.CodeAction(ctx, &protocol.CodeActionParams{
		TextDocument: protocol.TextDocumentIdentifier{URI: uri},
		Range:        rng,
		Context: protocol.CodeActionContext{
			Only:        kinds,
			Diagnostics: diagnostics,
		},
	})
	if err != nil {
		return fmt.Errorf("%v: %v", from, err)
	}

	// Gather edits from matching code actions.
	var edits []protocol.TextEdit
	for _, act := range actions {
		if act.Disabled != nil {
			continue
		}
		if !titleRE.MatchString(act.Title) {
			continue
		}

		// If the provided span has a position (not just offsets),
		// and the action has diagnostics, the action must have a
		// diagnostic with the same range as it.
		if from.HasPosition() && len(act.Diagnostics) > 0 &&
			!slices.ContainsFunc(act.Diagnostics, func(diag protocol.Diagnostic) bool {
				return diag.Range.Start == rng.Start
			}) {
			continue
		}

		if cmd.Exec {
			// -exec: run the first matching code action.
			if act.Command != nil {
				// This may cause the server to make
				// an ApplyEdit downcall to the client.
				if _, err := executeCommand(ctx, cli.server, act.Command); err != nil {
					return err
				}
				// The specification says that commands should
				// be executed _after_ edits are applied, not
				// instead of them, but we don't want to
				// duplicate edits.
			} else {
				// Partially apply CodeAction.Edit, a WorkspaceEdit.
				// (See also cli.applyWorkspaceEdit(a.Edit)).
				for _, c := range act.Edit.DocumentChanges {
					tde := c.TextDocumentEdit
					if tde != nil && tde.TextDocument.URI == uri {
						// TODO(adonovan): this logic will butcher an edit that spans files.
						// It will also ignore create/delete/rename operations.
						// Fix or document. Need a three-way merge.
						edits = append(edits, protocol.AsTextEdits(tde.Edits)...)
					}
				}
				return applyTextEdits(file.mapper, edits, cmd.app.editFlags)
			}
			return nil
		} else {
			// No -exec: list matching code actions.
			action := "edit"
			if act.Command != nil {
				action = "command"
			}
			fmt.Printf("%s\t%q [%s]\n",
				action,
				act.Title,
				act.Kind)
		}
	}

	if cmd.Exec {
		return fmt.Errorf("no matching code action at %s", from)
	}
	return nil
}
