// Copyright 2025 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 cache

import (
	"context"
	"log"
	"maps"
	"slices"
	"strings"

	"golang.org/x/tools/gopls/internal/cache/metadata"
	"golang.org/x/tools/gopls/internal/cache/symbols"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/util/moremaps"
	"golang.org/x/tools/internal/imports"
)

// goplsSource is an imports.Source that provides import information using
// gopls and the module cache index.
type goplsSource struct {
	snapshot  *Snapshot
	envSource *imports.ProcessEnvSource

	// set by each invocation of ResolveReferences
	ctx context.Context
}

func (s *Snapshot) NewGoplsSource(is *imports.ProcessEnvSource) *goplsSource {
	return &goplsSource{
		snapshot:  s,
		envSource: is,
	}
}

func (s *goplsSource) LoadPackageNames(ctx context.Context, srcDir string, paths []imports.ImportPath) (map[imports.ImportPath]imports.PackageName, error) {
	// TODO: use metadata graph. Aside from debugging, this is the only used of envSource
	return s.envSource.LoadPackageNames(ctx, srcDir, paths)
}

type result struct {
	res        *imports.Result
	deprecated bool
}

// ResolveReferences tries to find resolving imports in the workspace, and failing
// that, in the module cache. It uses heuristics to decide among alternatives.
// The heuristics will usually prefer a v2 version, if there is one.
// TODO: It does not take advantage of hints provided by the user:
// 1. syntactic context: pkg.Name().Foo
// 3. already imported files in the same module
func (s *goplsSource) ResolveReferences(ctx context.Context, filename string, missing imports.References) ([]*imports.Result, error) {
	s.ctx = ctx
	// get results from the workspace. There will at most one for each package name
	fromWS, err := s.resolveWorkspaceReferences(filename, missing)
	if err != nil {
		return nil, err
	}
	// collect the ones that are still
	needed := maps.Clone(missing)
	for _, a := range fromWS {
		delete(needed, a.Package.Name)
	}
	// when debug (below) is gone, change this to: if len(needed) == 0 {return fromWS, nil}
	var fromCache []*result
	if len(needed) != 0 {
		var err error
		fromCache, err = s.resolveCacheReferences(needed)
		if err != nil {
			return nil, err
		}
		// trim cans to one per missing package.
		byPkgNm := make(map[string][]*result)
		for _, c := range fromCache {
			byPkgNm[c.res.Package.Name] = append(byPkgNm[c.res.Package.Name], c)
		}
		for k, v := range byPkgNm {
			fromWS = append(fromWS, s.bestCache(k, v))
		}
	}
	const debug = false
	if debug { // debugging.
		// what does the old one find?
		old, err := s.envSource.ResolveReferences(ctx, filename, missing)
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("fromCache:%d %s", len(fromCache), filename)
		for i, c := range fromCache {
			log.Printf("cans%d %#v %#v %v", i, c.res.Import, c.res.Package, c.deprecated)
		}
		for k, v := range missing {
			for x := range v {
				log.Printf("missing %s.%s", k, x)
			}
		}
		for k, v := range needed {
			for x := range v {
				log.Printf("needed %s.%s", k, x)
			}
		}

		dbgpr := func(hdr string, v []*imports.Result) {
			for i := range v {
				log.Printf("%s%d %+v %+v", hdr, i, v[i].Import, v[i].Package)
			}
		}

		dbgpr("fromWS", fromWS)
		dbgpr("old", old)
		for k, v := range s.snapshot.workspacePackages.All() {
			log.Printf("workspacePackages[%s]=%s", k, v)
		}
		// anything in ans with >1 matches?
		seen := make(map[string]int)
		for _, a := range fromWS {
			seen[a.Package.Name]++
		}
		for k, v := range seen {
			if v > 1 {
				log.Printf("saw %d %s", v, k)
				for i, x := range fromWS {
					if x.Package.Name == k {
						log.Printf("%d: %+v %+v", i, x.Package, x.Import)
					}
				}
			}
		}
	}
	return fromWS, nil

}

func (s *goplsSource) resolveCacheReferences(missing imports.References) ([]*result, error) {
	ix, err := s.snapshot.view.ModcacheIndex()
	if err != nil {
		return nil, err
	}

	found := make(map[string]*result)
	for pkgName, nameSet := range missing {
		names := moremaps.KeySlice(nameSet)
		for importPath, cands := range ix.LookupAll(pkgName, names...) {
			res := found[importPath]
			if res == nil {
				res = &result{
					res: &imports.Result{
						Import: &imports.ImportInfo{
							ImportPath: importPath,
						},
						Package: &imports.PackageInfo{
							Name:    pkgName,
							Exports: make(map[string]bool)},
					},
					deprecated: false,
				}
				found[importPath] = res
			}
			for _, c := range cands {
				res.res.Package.Exports[c.Name] = true
				// The import path is deprecated if a symbol that would be used is deprecated
				res.deprecated = res.deprecated || c.Deprecated
			}
		}

	}
	return moremaps.ValueSlice(found), nil
}

type found struct {
	sym *symbols.Package
	res *imports.Result
}

func (s *goplsSource) resolveWorkspaceReferences(filename string, missing imports.References) ([]*imports.Result, error) {
	uri := protocol.URIFromPath(filename)
	mypkgs, err := s.snapshot.MetadataForFile(s.ctx, uri)
	if err != nil {
		return nil, err
	}
	if len(mypkgs) == 0 {
		return nil, nil
	}
	mypkg := mypkgs[0] // narrowest package
	// search the metadata graph for package ids correstponding to missing
	g := s.snapshot.MetadataGraph()
	var ids []metadata.PackageID
	var pkgs []*metadata.Package
	for pid, pkg := range g.Packages {
		// no test packages, except perhaps for ourselves
		if pkg.ForTest != "" && pkg != mypkg {
			continue
		}
		if missingWants(missing, pkg.Name) {
			ids = append(ids, pid)
			pkgs = append(pkgs, pkg)
		}
	}
	// find the symbols in those packages
	// the syms occur in the same order as the ids and the pkgs
	syms, err := s.snapshot.Symbols(s.ctx, ids...)
	if err != nil {
		return nil, err
	}
	// keep track of used syms and found results by package name
	// TODO: avoid import cycles (is current package in forward closure)
	founds := make(map[string][]found)
	for i := range len(ids) {
		nm := string(pkgs[i].Name)
		if satisfies(syms[i], missing[nm]) {
			got := &imports.Result{
				Import: &imports.ImportInfo{
					Name:       "",
					ImportPath: string(pkgs[i].PkgPath),
				},
				Package: &imports.PackageInfo{
					Name:    string(pkgs[i].Name),
					Exports: missing[imports.PackageName(pkgs[i].Name)],
				},
			}
			founds[nm] = append(founds[nm], found{syms[i], got})
		}
	}
	var ans []*imports.Result
	for _, v := range founds {
		// make sure the elements of v are unique
		// (Import.ImportPath or Package.Name must differ)
		cmp := func(l, r found) int {
			switch strings.Compare(l.res.Import.ImportPath, r.res.Import.ImportPath) {
			case -1:
				return -1
			case 1:
				return 1
			}
			return strings.Compare(l.res.Package.Name, r.res.Package.Name)
		}
		slices.SortFunc(v, cmp)
		newv := make([]found, 0, len(v))
		newv = append(newv, v[0])
		for i := 1; i < len(v); i++ {
			if cmp(v[i], v[i-1]) != 0 {
				newv = append(newv, v[i])
			}
		}
		ans = append(ans, bestImport(filename, newv))
	}
	return ans, nil
}

// for each package name, choose one using heuristics
func bestImport(filename string, got []found) *imports.Result {
	if len(got) == 1 {
		return got[0].res
	}
	isTestFile := strings.HasSuffix(filename, "_test.go")
	var leftovers []found
	for _, g := range got {
		// don't use _test packages unless isTestFile
		testPkg := strings.HasSuffix(string(g.res.Package.Name), "_test") || strings.HasSuffix(string(g.res.Import.Name), "_test")
		if testPkg && !isTestFile {
			continue // no test covers this
		}
		if imports.CanUse(filename, g.sym.Files[0].DirPath()) {
			leftovers = append(leftovers, g)
		}
	}
	switch len(leftovers) {
	case 0:
		break // use got, they are all bad
	case 1:
		return leftovers[0].res // only one left
	default:
		got = leftovers // filtered some out
	}

	// TODO: if there are versions (like /v2) prefer them

	// use distance to common ancestor with filename
	// (TestDirectoryFilters_MultiRootImportScanning)
	// filename is .../a/main.go, choices are
	// .../a/hi/hi.go and .../b/hi/hi.go
	longest := -1
	ix := -1
	for i := 0; i < len(got); i++ {
		d := commonpref(filename, got[i].sym.Files[0].Path())
		if d > longest {
			longest = d
			ix = i
		}
	}
	// it is possible that there were several tied, but we return the first
	return got[ix].res
}

// choose the best result for the package named nm from the module cache
func (s *goplsSource) bestCache(nm string, got []*result) *imports.Result {
	if len(got) == 1 {
		return got[0].res
	}
	// does the go.mod file choose one?
	if ans := s.fromGoMod(got); ans != nil {
		return ans
	}
	got = preferUndeprecated(got)
	// want the best Import.ImportPath
	// these are all for the package named nm,
	// nm (probably) occurs in all the paths;
	// choose the longest (after nm), so as to get /v2
	maxlen, which := -1, -1
	for i := 0; i < len(got); i++ {
		ix := strings.Index(got[i].res.Import.ImportPath, nm)
		if ix == -1 {
			continue // now what?
		}
		cnt := len(got[i].res.Import.ImportPath) - ix
		if cnt > maxlen {
			maxlen = cnt
			which = i
		}
		// what about ties? (e.g., /v2 and /v3)
	}
	if which >= 0 {
		return got[which].res
	}
	return got[0].res // arbitrary guess
}

// if go.mod requires one of the packages, return that
func (s *goplsSource) fromGoMod(got []*result) *imports.Result {
	// should we use s.S.view.worsspaceModFiles, and the union of their requires?
	// (note that there are no tests where it contains more than one)
	modURI := s.snapshot.view.gomod
	modfh, ok := s.snapshot.files.get(modURI)
	if !ok {
		return nil
	}
	parsed, err := s.snapshot.ParseMod(s.ctx, modfh)
	if err != nil {
		return nil
	}
	reqs := parsed.File.Require
	for _, g := range got {
		for _, req := range reqs {
			if strings.HasPrefix(g.res.Import.ImportPath, req.Syntax.Token[1]) {
				return g.res
			}
		}
	}
	return nil
}

func commonpref(filename string, path string) int {
	k := 0
	for ; k < len(filename) && k < len(path) && filename[k] == path[k]; k++ {
	}
	return k
}

func satisfies(pkg *symbols.Package, missing map[string]bool) bool {
	syms := make(map[string]bool)
	for _, x := range pkg.Symbols {
		for _, s := range x {
			syms[s.Name] = true
		}
	}
	for k := range missing {
		if !syms[k] {
			return false
		}
	}
	return true
}

// does pkgPath potentially satisfy a missing reference?
func missingWants(missing imports.References, pkgPath metadata.PackageName) bool {
	for k := range missing {
		if string(k) == string(pkgPath) {
			return true
		}
	}
	return false
}

// If there are both deprecated and undprecated ones
// then return only the undeprecated one
func preferUndeprecated(got []*result) []*result {
	var ok []*result
	for _, g := range got {
		if !g.deprecated {
			ok = append(ok, g)
		}
	}
	if len(ok) > 0 {
		return ok
	}
	return got
}
