// 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 splitpkg

// This file produces the "Split package" HTML report.
//
// The server persistently holds, for each PackageID, the current set
// of components and the mapping from declared names to components. On
// each page reload or JS reload() call, the server type-checks the
// package, computes its symbol reference graph, projects it onto
// components, then returns the component reference graph, and if it
// is cyclic, which edges form cycles. Thus changes to the package
// source are reflected in the client UI at the next page reload or JS
// reload() event.
//
// See also:
// - ../codeaction.go - offers the CodeAction command
// - ../../server/command.go - handles the command by opening a web page
// - ../../server/server.go - handles the HTTP request and calls this function
// - ../../server/assets/splitpkg.js - client-side logic
// - ../../test/integration/web/splitpkg_test.go - integration test of server
//
// TODO(adonovan): future work
//
// Refine symbol reference graph:
// - deal with enums (values must stay together; implicit dependency on iota expression)
// - deal with coupled vars "var x, y = f()"
// - deal with declared methods (coupled to receiver named type)
// - deal with fields/interface methods (loosely coupled to struct/interface type)
//   In both cases the field/method name must be either exported or in the same component.
//
// UI:
// - make shift click extend selection of a range of checkboxes.
// - display two-level grouping of decls and specs: var ( x int; y int )
// - indicate when package has type errors (data may be incomplete).
//
// Code transformation:
// - add "Split" button that is green when acyclic. It should:
//   1) move each component into a new package, or separate file of
//      the same package. (The UI will need to hold this user
//      intent in the list of components.)
//   2) ensure that each declaration referenced from another package
//      is public, renaming as needed.
//   3) update package decls, imports, package docs, file docs,
//      doc comments, etc.
// Should we call this feature "Reorganize package" or "Decompose package"
// until the "Split" button actually exists?

import (
	"bytes"
	"crypto/sha256"
	_ "embed"
	"encoding/json"
	"fmt"
	"go/ast"
	"go/token"
	"go/types"
	"html/template"
	"log"
	"strconv"
	"strings"

	"golang.org/x/tools/gopls/internal/cache"
	"golang.org/x/tools/gopls/internal/cache/metadata"
	"golang.org/x/tools/gopls/internal/filecache"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/util/moremaps"
	"golang.org/x/tools/gopls/internal/util/safetoken"
	"golang.org/x/tools/internal/typesinternal"
)

//go:embed splitpkg.html.tmpl
var htmlTmpl string

// HTML returns the HTML for the main "Split package" page, for the
// /splitpkg endpoint. The real magic happens in JavaScript; see
// ../../server/assets/splitpkg.js.
func HTML(pkgpath metadata.PackagePath) []byte {
	t, err := template.New("splitpkg.html").Parse(htmlTmpl)
	if err != nil {
		log.Fatal(err)
	}
	data := struct {
		Title string
	}{
		Title: fmt.Sprintf("Split package %s", pkgpath),
	}
	var buf bytes.Buffer
	if err := t.Execute(&buf, data); err != nil {
		log.Fatal(err)
	}
	return buf.Bytes()
}

const cacheKind = "splitpkg" // filecache kind

func cacheKey(pkgID metadata.PackageID) [32]byte {
	return sha256.Sum256([]byte(pkgID))
}

// UpdateComponentsJSON parses the JSON description of components and
// their assigned declarations and updates the component state for the
// specified package.
func UpdateComponentsJSON(pkgID metadata.PackageID, data []byte) error {
	return filecache.Set(cacheKind, cacheKey(pkgID), data)
}

// Web is an abstraction of gopls' web server.
type Web interface {
	// SrcURL forms URLs that cause the editor to open a file at a specific position.
	SrcURL(filename string, line, col8 int) protocol.URI
}

// JSON returns the JSON encoding of the data needed by
// the /splitpkg-json endpoint for the specified package. It includes:
//   - the set of names declared by the package, grouped by file;
//   - the set of components and their assigned declarations from
//     the most recent call to [UpdateComponentsJSON]; and
//   - the component graph derived from them, along with the
//     sets of reference that give rise to each edge.
func JSON(pkg *cache.Package, web Web) ([]byte, error) {
	// Retrieve package's most recent state from the file cache.
	var comp ComponentsJSON
	data, err := filecache.Get(cacheKind, cacheKey(pkg.Metadata().ID), filecache.Bytes)
	if err != nil {
		if err != filecache.ErrNotFound {
			return nil, err
		}
		// cache miss: use zero value
	} else if err := json.Unmarshal(data, &comp); err != nil {
		return nil, err
	}

	// Prepare to construct symbol reference graph.
	var (
		info    = pkg.TypesInfo()
		symbols = make(map[types.Object]*symbol)
	)

	// setName records the UI name for an object.
	// (The UI name disambiguates "init", "_", etc.)
	setName := func(obj types.Object, name string) {
		symbols[obj] = &symbol{
			name:      name,
			component: comp.Assignments[name], // missing => "default"
		}
	}

	// Pass 1: name everything, since naming is order-dependent.
	var initCounter, blankCounter int
	for _, pgf := range pkg.CompiledGoFiles() {
		for _, decl := range pgf.File.Decls {
			switch decl := decl.(type) {
			case *ast.FuncDecl:
				if fn, ok := info.Defs[decl.Name].(*types.Func); ok {
					// For now we treat methods as first class decls,
					// but since they are coupled to the named type
					// they should be omitted in the UI for brevity.
					name := fn.Name()
					if recv := fn.Signature().Recv(); recv != nil {
						fn = fn.Origin()
						_, named := typesinternal.ReceiverNamed(recv)
						name = named.Obj().Name() + "." + name
					} else if name == "init" {
						// Disambiguate top-level init functions.
						name += suffix(&initCounter)
					}
					if name == "_" { // (function or method)
						name += suffix(&blankCounter)
					}
					setName(fn, name)
				}

			case *ast.GenDecl:
				switch decl.Tok {
				case token.CONST, token.VAR:
					for _, spec := range decl.Specs {
						spec := spec.(*ast.ValueSpec)
						for _, id := range spec.Names {
							if obj := info.Defs[id]; obj != nil {
								name := obj.Name()
								if name == "_" {
									name += suffix(&blankCounter)
								}
								setName(obj, name)
							}
						}
					}

				case token.TYPE:
					for _, spec := range decl.Specs {
						spec := spec.(*ast.TypeSpec)
						if obj := info.Defs[spec.Name]; obj != nil {
							name := obj.Name()
							if name == "_" {
								name += suffix(&blankCounter)
							}
							setName(obj, name)
						}
					}
				}
			}
		}
	}

	// Pass 2: compute symbol reference graph, project onto
	// component dependency graph, and build JSON response.
	var (
		files []*fileJSON
		refs  []*refJSON
	)
	for _, pgf := range pkg.CompiledGoFiles() {
		identURL := func(id *ast.Ident) string {
			posn := safetoken.Position(pgf.Tok, id.Pos())
			return web.SrcURL(posn.Filename, posn.Line, posn.Column)
		}
		newCollector := func(from *symbol) *refCollector {
			return &refCollector{
				from:     from,
				identURL: identURL,
				pkg:      pkg.Types(),
				info:     info,
				symbols:  symbols,
			}
		}
		var decls []*declJSON
		for _, decl := range pgf.File.Decls {
			var (
				kind  string
				specs []*specJSON
			)
			switch decl := decl.(type) {
			case *ast.FuncDecl:
				kind = "func"
				if fn, ok := info.Defs[decl.Name].(*types.Func); ok {
					symbol := symbols[fn]
					rc := newCollector(symbol).collect(decl)
					refs = append(refs, rc.refs...)
					specs = append(specs, &specJSON{
						Name: symbol.name,
						URL:  identURL(decl.Name),
					})
				}

			case *ast.GenDecl:
				kind = decl.Tok.String()

				switch decl.Tok {
				case token.CONST, token.VAR:
					for _, spec := range decl.Specs {
						spec := spec.(*ast.ValueSpec)
						for i, id := range spec.Names {
							if obj := info.Defs[id]; obj != nil {
								symbol := symbols[obj]
								rc := newCollector(symbol)
								// If there's a type,
								// all RHSs depend on it.
								if spec.Type != nil {
									rc.collect(spec.Type)
								}
								switch len(spec.Values) {
								case len(spec.Names):
									// var x, y = a, b
									rc.collect(spec.Values[i])
								case 1:
									// var x, y = f()
									rc.collect(spec.Values[0])
								case 0:
									// var x T
								}
								refs = append(refs, rc.refs...)
								specs = append(specs, &specJSON{
									Name: symbol.name,
									URL:  identURL(id),
								})
							}
						}
					}

				case token.TYPE:
					for _, spec := range decl.Specs {
						spec := spec.(*ast.TypeSpec)
						if obj := info.Defs[spec.Name]; obj != nil {
							symbol := symbols[obj]
							rc := newCollector(symbol).collect(spec.Type)
							refs = append(refs, rc.refs...)
							specs = append(specs, &specJSON{
								Name: symbol.name,
								URL:  identURL(spec.Name),
							})
						}
					}
				}
			}
			if len(specs) > 0 {
				decls = append(decls, &declJSON{Kind: kind, Specs: specs})
			}
		}
		files = append(files, &fileJSON{
			Base:  pgf.URI.Base(),
			URL:   web.SrcURL(pgf.URI.Path(), 1, 1),
			Decls: decls,
		})
	}

	// Compute the graph of dependencies between components, by
	// projecting the symbol dependency graph through component
	// assignments.
	var (
		g        = make(graph)
		edgeRefs = make(map[[2]int][]*refJSON) // refs that induce each intercomponent edge
	)
	for _, ref := range refs {
		from, to := ref.from, ref.to
		if from.component != to.component {
			// inter-component reference
			m, ok := g[from.component]
			if !ok {
				m = make(map[int]bool)
				g[from.component] = m
			}
			m[to.component] = true

			key := [2]int{from.component, to.component}
			edgeRefs[key] = append(edgeRefs[key], ref)
		}
	}

	// Detect cycles in the component graph
	// and record cyclic (⚠) components.
	cycles := [][]int{}        // non-nil for JSON
	scmap := make(map[int]int) // maps component index to 1 + SCC index (0 => acyclic)
	for i, scc := range sccs(g) {
		for c := range scc {
			scmap[c] = i + 1
		}
		cycles = append(cycles, moremaps.KeySlice(scc))
	}

	// Record intercomponent edges and their references.
	edges := []*edgeJSON{} // non-nil for JSON
	for edge, refs := range edgeRefs {
		from, to := edge[0], edge[1]
		edges = append(edges, &edgeJSON{
			From:   from,
			To:     to,
			Refs:   refs,
			Cyclic: scmap[from] > 0 && scmap[from] == scmap[to],
		})
	}

	return json.Marshal(ResultJSON{
		Files:      files,
		Components: comp,
		Edges:      edges,
		Cycles:     cycles,
	})
}

// A refCollector gathers intra-package references to top-level
// symbols from within one syntax tree, in lexical order.
type refCollector struct {
	from     *symbol
	identURL func(*ast.Ident) string
	pkg      *types.Package
	info     *types.Info
	index    map[types.Object]*refJSON
	symbols  map[types.Object]*symbol

	refs []*refJSON // output
}

// A symbol describes a declared name and its assigned component.
type symbol struct {
	name      string // unique name in the UI and JSON/HTTP protocol
	component int    // index of assigned component
}

// collect adds the free references of n to the collection.
func (rc *refCollector) collect(n ast.Node) *refCollector {
	var f func(n ast.Node) bool
	f = func(n ast.Node) bool {
		switch n := n.(type) {
		case *ast.SelectorExpr:
			if sel, ok := rc.info.Selections[n]; ok {
				rc.addRef(n.Sel, sel.Obj())
				ast.Inspect(n.X, f)
				return false // don't visit n.Sel
			}

		case *ast.Ident:
			if obj := rc.info.Uses[n]; obj != nil {
				rc.addRef(n, obj)
			}
		}
		return true
	}
	ast.Inspect(n, f)

	return rc
}

// addRef records a reference from id to obj.
func (rc *refCollector) addRef(id *ast.Ident, obj types.Object) {
	if obj.Pkg() != rc.pkg {
		return // cross-package reference
	}

	// Un-instantiate methods.
	if fn, ok := obj.(*types.Func); ok && fn.Signature().Recv() != nil {
		obj = fn.Origin() // G[int].method -> G[T].method
	}

	// We only care about refs to package-level symbols.
	// And methods, for now.
	decl := rc.symbols[obj]
	if decl == nil {
		return // not a package-level symbol or top-level method
	}

	if ref, ok := rc.index[obj]; !ok {
		ref = &refJSON{
			From: rc.from.name,
			To:   decl.name,
			URL:  rc.identURL(id),
			from: rc.from,
			to:   decl,
		}
		if rc.index == nil {
			rc.index = make(map[types.Object]*refJSON)
		}
		rc.index[obj] = ref
		rc.refs = append(rc.refs, ref)
	}
}

// suffix returns a subscripted decimal suffix,
// preincrementing the specified counter.
func suffix(counter *int) string {
	*counter++
	n := *counter
	return subscripter.Replace(strconv.Itoa(n))
}

var subscripter = strings.NewReplacer(
	"0", "₀",
	"1", "₁",
	"2", "₂",
	"3", "₃",
	"4", "₄",
	"5", "₅",
	"6", "₆",
	"7", "₇",
	"8", "₈",
	"9", "₉",
)

// -- JSON types --

// ResultJSON describes the result of a /splitpkg-json query.
// It is public for testing.
type ResultJSON struct {
	Components ComponentsJSON // component names and their assigned declarations
	Files      []*fileJSON    // files of the packages and their declarations and references
	Edges      []*edgeJSON    // inter-component edges and their references
	Cycles     [][]int        // sets of strongly-connected components
}

// request body of a /splitpkg-components update;
// also part of /splitpkg-json response.
type ComponentsJSON struct {
	Names       []string       `json:",omitempty"` // if empty, implied Names[0]=="default".
	Assignments map[string]int `json:",omitempty"` // maps specJSON.Name to component index; missing => 0
}

// edgeJSON describes an inter-component dependency.
type edgeJSON struct {
	From, To int        // component IDs
	Refs     []*refJSON // references that give rise to this edge
	Cyclic   bool       // edge is part of nontrivial strongly connected component
}

// fileJSON records groups decl/spec information about a single file.
type fileJSON struct {
	Base  string      // file base name
	URL   string      // showDocument link for file
	Decls []*declJSON `json:",omitempty"`
}

// declJSON groups specs (e.g. "var ( x int; y int )").
type declJSON struct {
	Kind  string      // const, var, type, func
	Specs []*specJSON `json:",omitempty"`
}

// specJSON describes a single declared name.
// (A coupled declaration "var x, y = f()" results in two specJSONs.)
type specJSON struct {
	Name string // x or T.x
	URL  string // showDocument link for declaring identifier
}

// refJSON records the first reference from a given declaration to a symbol.
// (Repeat uses of the same identifier are omitted.)
type refJSON struct {
	From, To string // x or T.x of referenced spec
	URL      string // showDocument link for referring identifier

	from, to *symbol // transient
}
