// 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/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 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
}
