// Copyright 2026 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 golang

import (
	"context"
	"fmt"
	"go/ast"
	"go/types"
	"strings"

	"golang.org/x/tools/gopls/internal/cache"
	"golang.org/x/tools/gopls/internal/cache/metadata"
	"golang.org/x/tools/gopls/internal/golang/stubmethods"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/util/cursorutil"
	internalastutil "golang.org/x/tools/internal/astutil"
	"golang.org/x/tools/internal/packagepath"
	"golang.org/x/tools/internal/typesinternal"
)

// ImplementInterface generates workspace edits to add method stubs, making the
// package-level type at the given location implement the target interface.
//
// The ifaceStr must be "error" or a fully qualified name (e.g.,
// "example.com/pkg.Type").
func ImplementInterface(ctx context.Context, snapshot *cache.Snapshot, loc protocol.Location, ifaceStr string) (changes []protocol.DocumentChange, _ error) {
	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, loc.URI)
	if err != nil {
		return nil, err
	}

	metadataPkgForPath := func(pkgPath string) (*metadata.Package, error) {
		mps, ok := snapshot.MetadataGraph().ForPackagePath[metadata.PackagePath(pkgPath)]
		if !ok {
			return nil, fmt.Errorf("package %q is not in the workspace", pkgPath)
		}

		if len(mps) == 0 {
			return nil, fmt.Errorf("no package metadata for package %q", pkgPath)
		}

		return mps[0], nil
	}

	var (
		iface    *types.TypeName
		ifacePkg *cache.Package
	)
	{
		if ifaceStr == "error" {
			iface = types.Universe.Lookup("error").(*types.TypeName)
		} else {
			lastDot := strings.LastIndex(ifaceStr, ".")
			if lastDot == -1 {
				return nil, fmt.Errorf(
					`invalid interface type name (want string of form "example.com/pkg.Type"`)
			} else {
				// Do not assume the target package is already imported or type-checked
				// in the current context. Look it up globally via the metadata graph.
				pkgPath := ifaceStr[:lastDot]
				symName := ifaceStr[lastDot+1:]

				mp, err := metadataPkgForPath(pkgPath)
				if err != nil {
					return nil, err
				}

				pkgs, err := snapshot.TypeCheck(ctx, mp.ID)
				if err != nil {
					return nil, err
				}

				ifacePkg = pkgs[0]

				obj := ifacePkg.Types().Scope().Lookup(symName)
				if obj == nil {
					return nil, fmt.Errorf("symbol %q not found in package %q", symName, pkgPath)
				}

				var ok bool
				iface, ok = obj.(*types.TypeName)
				if !ok {
					return nil, fmt.Errorf("%s.%s is a %s, not a type", pkgPath, symName, typesinternal.ObjectKind(obj))
				}

				if !types.IsInterface(iface.Type()) {
					return nil, fmt.Errorf("%s.%s is not an interface", pkgPath, symName)
				}
			}
		}
	}

	var (
		named    *types.Named
		namedPkg *metadata.Package
	)
	{
		start, end, err := pgf.RangePos(loc.Range)
		if err != nil {
			return nil, err
		}
		cur, _, _, _ := internalastutil.Select(pgf.Cursor(), start, end) // can't fail: pgf contains pos

		spec, curSpec := cursorutil.FirstEnclosing[*ast.TypeSpec](cur)
		if spec == nil {
			return nil, fmt.Errorf("no enclosing type declaration")
		}

		// Only package level.
		if curSpec.Parent().Parent().Node() != pgf.File {
			return nil, fmt.Errorf("enclosing type %s is not at package level", spec.Name.Name)
		}

		t, ok := types.Unalias(pkg.TypesInfo().TypeOf(spec.Name)).(*types.Named)
		if !ok {
			return nil, fmt.Errorf("enclosing type is not a named type")
		}

		if is[*types.Pointer](t.Underlying()) {
			return nil, fmt.Errorf("cannot declare concrete methods on a pointer type %s", t.Obj().Name())
		}

		if types.IsInterface(t) {
			return nil, fmt.Errorf("cannot declare concrete methods on a interface type %s", t.Obj().Name())
		}

		named = t
		namedPkgPath := t.Obj().Pkg().Path()

		namedPkg, err = metadataPkgForPath(namedPkgPath)
		if err != nil {
			return nil, err
		}
	}

	// Reject cases that would add cycle-forming or disallowed internal imports
	// for types mentioned in the added methods.
	if ifaceStr != "error" && namedPkg != ifacePkg.Metadata() {
		// extraPackages maps each referenced package to the method that introduced it.
		extraPackages := make(map[*types.Package]*types.Func)
		dependingOnX := snapshot.MetadataGraph().ReverseReflexiveTransitiveClosure(namedPkg.ID)
		for m := range iface.Type().Underlying().(*types.Interface).Methods() {
			if !m.Exported() {
				return nil, fmt.Errorf("cannot add unexported method %s from package %s to type %s", m.Name(), namedPkg.Name, named.Obj().Name())
			}
			// Extract all packages referenced in the method signature.
			_ = types.TypeString(m.Type(), func(p *types.Package) string {
				extraPackages[p] = m
				return ""
			})
		}
		for p, method := range extraPackages {
			mp, err := metadataPkgForPath(p.Path())
			if err != nil {
				return nil, err
			}

			if _, ok := dependingOnX[mp.ID]; ok {
				return nil, fmt.Errorf("adding method %s to type %s would create an import cycle", method.Name(), named.Obj().Name())
			}

			if !packagepath.CanImport(namedPkg.String(), p.Path()) {
				return nil, fmt.Errorf("adding method %s to type %s would require import of inaccessible package %s", method.Name(), named.Obj().Name(), p.Name())
			}
		}
	}

	// TODO(hxjiang): if the package contains the interface is visible and
	// importable from the package contains the named type, consider add:
	//    var _ Interface = (*Type)(nil)
	si := stubmethods.IfaceStubInfo{
		Fset:      pkg.FileSet(),
		Interface: iface,
		Concrete:  named,
		// TODO(hxjiang): consider make it question and let the user decide
		// whether to use pointer receiver or not.
		Pointer: true, // by default, use pointer receiver
	}

	// TODO(hxjiang): fix the comment position after insert the methods, see test
	// result in testdata/codeaction/implement_interface.txt basic/good/good.go
	fixFset, suggestion, err := insertDeclsAfter(ctx, snapshot, pkg.Metadata(), si.Fset, si.Concrete.Obj(), si.Emit)
	if err != nil {
		return nil, err
	}

	return suggestedFixToDocumentChange(ctx, snapshot, fixFset, suggestion)
}
