// 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.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
	conn, err := cmd.app.connect(ctx)
	if err != nil {
		return err
	}
	defer conn.terminate(ctx)

	from := parseSpan(args[0])
	uri := from.URI()
	file, err := conn.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 := conn.diagnoseFiles(ctx, []protocol.DocumentURI{uri}); err != nil {
		return err
	}
	diagnostics := []protocol.Diagnostic{} // LSP wants non-nil slice
	conn.client.filesMu.Lock()
	diagnostics = append(diagnostics, file.diagnostics...)
	conn.client.filesMu.Unlock()

	// Request code actions of the desired kinds.
	var kinds []protocol.CodeActionKind
	if cmd.Kind != "" {
		for _, kind := range strings.Split(cmd.Kind, ",") {
			kinds = append(kinds, protocol.CodeActionKind(kind))
		}
	} else {
		kinds = append(kinds, protocol.Empty) // => all
	}
	actions, err := conn.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 := conn.executeCommand(ctx, 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 conn.Client.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
}
