// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package python

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/bazelbuild/bazel-gazelle/config"
	"github.com/bazelbuild/bazel-gazelle/label"
	"github.com/bazelbuild/bazel-gazelle/repo"
	"github.com/bazelbuild/bazel-gazelle/resolve"
	"github.com/bazelbuild/bazel-gazelle/rule"
	bzl "github.com/bazelbuild/buildtools/build"
	"github.com/emirpasic/gods/sets/treeset"
	godsutils "github.com/emirpasic/gods/utils"

	"github.com/bazel-contrib/rules_python/gazelle/pythonconfig"
)

const languageName = "py"

const (
	// resolvedDepsKey is the attribute key used to pass dependencies that don't
	// need to be resolved by the dependency resolver in the Resolver step.
	resolvedDepsKey = "_gazelle_python_resolved_deps"
)

// Resolver satisfies the resolve.Resolver interface. It resolves dependencies
// in rules generated by this extension.
type Resolver struct{}

// Name returns the name of the language. This is the prefix of the kinds of
// rules generated. E.g. py_library and py_binary.
func (*Resolver) Name() string { return languageName }

// Imports returns a list of ImportSpecs that can be used to import the rule
// r. This is used to populate RuleIndex.
//
// If nil is returned, the rule will not be indexed. If any non-nil slice is
// returned, including an empty slice, the rule will be indexed.
func (py *Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec {
	cfgs := c.Exts[languageName].(pythonconfig.Configs)
	cfg := cfgs[f.Pkg]
	srcs := r.AttrStrings("srcs")
	provides := make([]resolve.ImportSpec, 0, len(srcs)+1)
	for _, src := range srcs {
		ext := filepath.Ext(src)
		if ext != ".py" {
			continue
		}
		if cfg.PerFileGeneration() && len(srcs) > 1 && src == pyLibraryEntrypointFilename {
			// Do not provide import spec from __init__.py when it is being included as
			// part of another module.
			continue
		}
		pythonProjectRoot := cfg.PythonProjectRoot()
		provide := importSpecFromSrc(pythonProjectRoot, f.Pkg, src)
		provides = append(provides, provide)
	}
	if len(provides) == 0 {
		return nil
	}
	return provides
}

// importSpecFromSrc determines the ImportSpec based on the target that contains the src so that
// the target can be indexed for import statements that match the calculated src relative to the its
// Python project root.
func importSpecFromSrc(pythonProjectRoot, bzlPkg, src string) resolve.ImportSpec {
	pythonPkgDir := filepath.Join(bzlPkg, filepath.Dir(src))
	relPythonPkgDir, err := filepath.Rel(pythonProjectRoot, pythonPkgDir)
	if err != nil {
		panic(fmt.Errorf("unexpected failure: %v", err))
	}
	if relPythonPkgDir == "." {
		relPythonPkgDir = ""
	}
	pythonPkg := strings.ReplaceAll(relPythonPkgDir, "/", ".")
	filename := filepath.Base(src)
	if filename == pyLibraryEntrypointFilename {
		if pythonPkg != "" {
			return resolve.ImportSpec{
				Lang: languageName,
				Imp:  pythonPkg,
			}
		}
	}
	moduleName := strings.TrimSuffix(filename, ".py")
	var imp string
	if pythonPkg == "" {
		imp = moduleName
	} else {
		imp = fmt.Sprintf("%s.%s", pythonPkg, moduleName)
	}
	return resolve.ImportSpec{
		Lang: languageName,
		Imp:  imp,
	}
}

// Embeds returns a list of labels of rules that the given rule embeds. If
// a rule is embedded by another importable rule of the same language, only
// the embedding rule will be indexed. The embedding rule will inherit
// the imports of the embedded rule.
func (py *Resolver) Embeds(r *rule.Rule, from label.Label) []label.Label {
	// TODO(f0rmiga): implement.
	return make([]label.Label, 0)
}

// addDependency adds a dependency to either the regular deps or pyiDeps set based on
// whether the module is type-checking only. If a module is added as both
// non-type-checking and type-checking, it should end up in deps and not pyiDeps.
func addDependency(dep string, typeCheckingOnly bool, deps, pyiDeps *treeset.Set) {
	if typeCheckingOnly {
		if !deps.Contains(dep) {
			pyiDeps.Add(dep)
		}
	} else {
		deps.Add(dep)
		pyiDeps.Remove(dep)
	}
}

// Resolve translates imported libraries for a given rule into Bazel
// dependencies. Information about imported libraries is returned for each
// rule generated by language.GenerateRules in
// language.GenerateResult.Imports. Resolve generates a "deps" attribute (or
// the appropriate language-specific equivalent) for each import according to
// language-specific rules and heuristics.
func (py *Resolver) Resolve(
	c *config.Config,
	ix *resolve.RuleIndex,
	rc *repo.RemoteCache,
	r *rule.Rule,
	modulesRaw interface{},
	from label.Label,
) {
	// TODO(f0rmiga): may need to be defensive here once this Gazelle extension
	// join with the main Gazelle binary with other rules. It may conflict with
	// other generators that generate py_* targets.
	deps := treeset.NewWith(godsutils.StringComparator)
	pyiDeps := treeset.NewWith(godsutils.StringComparator)
	cfgs := c.Exts[languageName].(pythonconfig.Configs)
	cfg := cfgs[from.Pkg]

	if modulesRaw != nil {
		pythonProjectRoot := cfg.PythonProjectRoot()
		modules := modulesRaw.(*treeset.Set)
		it := modules.Iterator()
		explainDependency := os.Getenv("EXPLAIN_DEPENDENCY")
		hasFatalError := false
	MODULES_LOOP:
		for it.Next() {
			mod := it.Value().(Module)
			moduleName := mod.Name
			// Transform relative imports `.` or `..foo.bar` into the package path from root.
			if strings.HasPrefix(mod.From, ".") {
				if !cfg.ExperimentalAllowRelativeImports() {
					continue MODULES_LOOP
				}

				// Count number of leading dots in mod.From (e.g., ".." = 2, "...foo.bar" = 3)
				relativeDepth := strings.IndexFunc(mod.From, func(r rune) bool { return r != '.' })
				if relativeDepth == -1 {
					relativeDepth = len(mod.From)
				}

				// Extract final symbol (e.g., "some_function") from mod.Name
				imported := mod.Name
				if idx := strings.LastIndex(mod.Name, "."); idx >= 0 {
					imported = mod.Name[idx+1:]
				}

				// Optional subpath in 'from' clause, e.g. "from ...my_library.foo import x"
				fromPath := strings.TrimLeft(mod.From, ".")
				var fromParts []string
				if fromPath != "" {
					fromParts = strings.Split(fromPath, ".")
				}

				// Current Bazel package as path segments
				pkgParts := strings.Split(from.Pkg, "/")

				if relativeDepth-1 > len(pkgParts) {
					log.Printf("ERROR: Invalid relative import %q in %q: exceeds package root.", mod.Name, mod.Filepath)
					continue MODULES_LOOP
				}

				// Go up relativeDepth - 1 levels
				baseParts := pkgParts
				if relativeDepth > 1 {
					baseParts = pkgParts[:len(pkgParts)-(relativeDepth-1)]
				}
				// Build absolute module path
				absParts := append([]string{}, baseParts...) // base path
				absParts = append(absParts, fromParts...)    // subpath from 'from'
				absParts = append(absParts, imported)        // actual imported symbol

				moduleName = strings.Join(absParts, ".")
			}

			moduleParts := strings.Split(moduleName, ".")
			possibleModules := []string{moduleName}
			for len(moduleParts) > 1 {
				// Iterate back through the possible imports until
				// a match is found.
				// For example, "from foo.bar import baz" where baz is a module, we should try `foo.bar.baz` first, then
				// `foo.bar`, then `foo`.
				// In the first case, the import could be file `baz.py` in the directory `foo/bar`.
				// Or, the import could be variable `baz` in file `foo/bar.py`.
				// The import could also be from a standard module, e.g. `six.moves`, where
				// the dependency is actually `six`.
				moduleParts = moduleParts[:len(moduleParts)-1]
				possibleModules = append(possibleModules, strings.Join(moduleParts, "."))
			}
			errs := []error{}
		POSSIBLE_MODULE_LOOP:
			for _, moduleName := range possibleModules {
				imp := resolve.ImportSpec{Lang: languageName, Imp: moduleName}
				if override, ok := resolve.FindRuleWithOverride(c, imp, languageName); ok {
					if override.Repo == "" {
						override.Repo = from.Repo
					}
					if !override.Equal(from) {
						if override.Repo == from.Repo {
							override.Repo = ""
						}
						dep := override.Rel(from.Repo, from.Pkg).String()
						addDependency(dep, mod.TypeCheckingOnly, deps, pyiDeps)
						if explainDependency == dep {
							log.Printf("Explaining dependency (%s): "+
								"in the target %q, the file %q imports %q at line %d, "+
								"which resolves using the \"gazelle:resolve\" directive.\n",
								explainDependency, from.String(), mod.Filepath, moduleName, mod.LineNumber)
						}
						continue MODULES_LOOP
					}
				} else {
					if dep, distributionName, ok := cfg.FindThirdPartyDependency(moduleName); ok {
						addDependency(dep, mod.TypeCheckingOnly, deps, pyiDeps)
						// Add the type and stub dependencies if they exist.
						modules := []string{
							fmt.Sprintf("%s_stubs", strings.ToLower(distributionName)),
							fmt.Sprintf("%s_types", strings.ToLower(distributionName)),
							fmt.Sprintf("types_%s", strings.ToLower(distributionName)),
							fmt.Sprintf("stubs_%s", strings.ToLower(distributionName)),
						}
						for _, module := range modules {
							if dep, _, ok := cfg.FindThirdPartyDependency(module); ok {
								// Type stub packages are added as type-checking only.
								addDependency(dep, true, deps, pyiDeps)
							}
						}
						if explainDependency == dep {
							log.Printf("Explaining dependency (%s): "+
								"in the target %q, the file %q imports %q at line %d, "+
								"which resolves from the third-party module %q from the wheel %q.\n",
								explainDependency, from.String(), mod.Filepath, moduleName, mod.LineNumber, mod.Name, dep)
						}
						continue MODULES_LOOP
					} else {
						matches := ix.FindRulesByImportWithConfig(c, imp, languageName)
						if len(matches) == 0 {
							// Check if the imported module is part of the standard library.
							if isStdModule(Module{Name: moduleName}) {
								continue MODULES_LOOP
							} else if cfg.ValidateImportStatements() {
								err := fmt.Errorf(
									"%[1]q, line %[2]d: %[3]q is an invalid dependency: possible solutions:\n"+
										"\t1. Add it as a dependency in the requirements.txt file.\n"+
										"\t2. Use the '# gazelle:resolve py %[3]s TARGET_LABEL' BUILD file directive to resolve to a known dependency.\n"+
										"\t3. Ignore it with a comment '# gazelle:ignore %[3]s' in the Python file.\n",
									mod.Filepath, mod.LineNumber, moduleName,
								)
								errs = append(errs, err)
								continue POSSIBLE_MODULE_LOOP
							}
						}
						filteredMatches := make([]resolve.FindResult, 0, len(matches))
						for _, match := range matches {
							if match.IsSelfImport(from) {
								// Prevent from adding itself as a dependency.
								continue MODULES_LOOP
							}
							filteredMatches = append(filteredMatches, match)
						}
						if len(filteredMatches) == 0 {
							continue POSSIBLE_MODULE_LOOP
						}
						if len(filteredMatches) > 1 {
							sameRootMatches := make([]resolve.FindResult, 0, len(filteredMatches))
							for _, match := range filteredMatches {
								if strings.HasPrefix(match.Label.Pkg, pythonProjectRoot) {
									sameRootMatches = append(sameRootMatches, match)
								}
							}
							if len(sameRootMatches) != 1 {
								err := fmt.Errorf(
									"%[1]q, line %[2]d: multiple targets (%[3]s) may be imported with %[4]q: possible solutions:\n"+
										"\t1. Disambiguate the above multiple targets by removing duplicate srcs entries.\n"+
										"\t2. Use the '# gazelle:resolve py %[4]s TARGET_LABEL' BUILD file directive to resolve to one of the above targets.\n",
									mod.Filepath, mod.LineNumber, targetListFromResults(filteredMatches), moduleName)
								errs = append(errs, err)
								continue POSSIBLE_MODULE_LOOP
							}
							filteredMatches = sameRootMatches
						}
						matchLabel := filteredMatches[0].Label.Rel(from.Repo, from.Pkg)
						dep := matchLabel.String()
						addDependency(dep, mod.TypeCheckingOnly, deps, pyiDeps)
						if explainDependency == dep {
							log.Printf("Explaining dependency (%s): "+
								"in the target %q, the file %q imports %q at line %d, "+
								"which resolves from the first-party indexed labels.\n",
								explainDependency, from.String(), mod.Filepath, moduleName, mod.LineNumber)
						}
						continue MODULES_LOOP
					}
				}
			} // End possible modules loop.
			if len(errs) > 0 {
				// If, after trying all possible modules, we still haven't found anything, error out.
				joinedErrs := ""
				for _, err := range errs {
					joinedErrs = fmt.Sprintf("%s%s\n", joinedErrs, err)
				}
				log.Printf("ERROR: failed to validate dependencies for target %q:\n\n%v", from.String(), joinedErrs)
				hasFatalError = true
			}
		}
		if hasFatalError {
			os.Exit(1)
		}
	}

	addResolvedDeps(r, deps)

	if cfg.GeneratePyiDeps() {
		if !deps.Empty() {
			r.SetAttr("deps", convertDependencySetToExpr(deps))
		}
		if !pyiDeps.Empty() {
			r.SetAttr("pyi_deps", convertDependencySetToExpr(pyiDeps))
		}
	} else {
		// When generate_pyi_deps is false, merge both deps and pyiDeps into deps
		combinedDeps := treeset.NewWith(godsutils.StringComparator)
		combinedDeps.Add(deps.Values()...)
		combinedDeps.Add(pyiDeps.Values()...)

		if !combinedDeps.Empty() {
			r.SetAttr("deps", convertDependencySetToExpr(combinedDeps))
		}
	}
}

// addResolvedDeps adds the pre-resolved dependencies from the rule's private attributes
// to the provided deps set.
func addResolvedDeps(
	r *rule.Rule,
	deps *treeset.Set,
) {
	resolvedDeps := r.PrivateAttr(resolvedDepsKey).(*treeset.Set)
	if !resolvedDeps.Empty() {
		it := resolvedDeps.Iterator()
		for it.Next() {
			deps.Add(it.Value())
		}
	}
}

// targetListFromResults returns a string with the human-readable list of
// targets contained in the given results.
func targetListFromResults(results []resolve.FindResult) string {
	list := make([]string, len(results))
	for i, result := range results {
		list[i] = result.Label.String()
	}
	return strings.Join(list, ", ")
}

// convertDependencySetToExpr converts the given set of dependencies to an
// expression to be used in the deps attribute.
func convertDependencySetToExpr(set *treeset.Set) bzl.Expr {
	deps := make([]bzl.Expr, set.Size())
	it := set.Iterator()
	for it.Next() {
		dep := it.Value().(string)
		deps[it.Index()] = &bzl.StringExpr{Value: dep}
	}
	return &bzl.ListExpr{List: deps}
}
