package analyzers

import (
	"go/ast"
	"strings"

	"golang.org/x/tools/go/analysis"
)

// ManifestEnvironmentAnalyzer flags any function that returns manifest.Artifacts
// without explicitly setting the Environment field. This enforces the V.1 requirement
// that Artifacts must always include Environment information for provenance.
var ManifestEnvironmentAnalyzer = &analysis.Analyzer{
	Name: "manifestenv",
	Doc:  "flags functions returning Artifacts without Environment field set",
	Run:  runManifestEnvironment,
}

func runManifestEnvironment(pass *analysis.Pass) (interface{}, error) {
	for _, file := range pass.Files {
		ast.Inspect(file, func(n ast.Node) bool {
			// Look for return statements
			ret, ok := n.(*ast.ReturnStmt)
			if !ok {
				return true
			}

			// Check each returned value
			for _, result := range ret.Results {
				// Check if it's a struct literal
				composite, ok := result.(*ast.CompositeLit)
				if !ok {
					continue
				}

				// Check if the type is manifest.Artifacts
				typeInfo := pass.TypesInfo.TypeOf(composite)
				if typeInfo == nil {
					continue
				}

				typeStr := typeInfo.String()
				if !strings.Contains(typeStr, "manifest.Artifacts") && !strings.Contains(typeStr, "Artifacts") {
					continue
				}

				// Check if Environment field is set
				hasEnv := false
				for _, elt := range composite.Elts {
					kv, ok := elt.(*ast.KeyValueExpr)
					if !ok {
						continue
					}
					key, ok := kv.Key.(*ast.Ident)
					if !ok {
						continue
					}
					if key.Name == "Environment" {
						hasEnv = true
						break
					}
				}

				if !hasEnv {
					pass.Reportf(composite.Pos(),
						"returning Artifacts without Environment field set - Environment is required for provenance (V.1)")
				}
			}

			return true
		})
	}
	return nil, nil
}
