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

// Comments beginning with "api:" are read by RouteInfos.
// They should not be removed.
// If a new route is added, provide all the "api:" comments for it.

package api

import (
	"bytes"
	_ "embed"
	"encoding/json"
	"errors"
	"fmt"
	"go/parser"
	"maps"
	"net/http"
	"reflect"
	"slices"
	"strings"
	"time"

	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/godoc"
	"golang.org/x/pkgsite/internal/log"
	"golang.org/x/pkgsite/internal/stdlib"
	"golang.org/x/pkgsite/internal/version"
	"golang.org/x/pkgsite/internal/vuln"
)

const (
	// maxSearchResults is the maximum number of search results to return for a search query.
	maxSearchResults = 1000
	// defaultSearchLimit is the default number of results to return per page for search.
	defaultSearchLimit = 25
	// maxLimit is the maximum allowed limit for paginated results.
	maxLimit = 1000
	// defaultLimit is the default number of results to return per page for paginated results.
	defaultLimit = 100
)

// OpenAPISpec contains the raw bytes of the OpenAPI 3.0 specification for the API.
//
//go:embed openapi.yaml
var OpenAPISpec []byte

// ServePackage handles requests for the v1beta package metadata endpoint.
// api:route /v1beta/package/{path}
// api:desc Information about the package at {path}.
// api:example /v1beta/package/golang.org/x/time/rate
func ServePackage(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
	defer derrors.Wrap(&err, "ServePackage")

	pkgPath := trimPath(r, "/v1beta/package/")
	if pkgPath == "" {
		return BadRequest("missing package path",
			"the package path must be provided after '/package/'")
	}

	// api:params PackageParams
	var params PackageParams
	if err := ParseParams(r.URL.Query(), &params); err != nil {
		return err
	}

	if params.Examples && params.Doc == "" {
		return BadRequest("examples require doc format to be specified")
	}
	switch params.Doc {
	// renderDocumentation needs to be updated when the doc set changes.
	case "", "text", "md", "markdown", "html":
	default:
		return BadRequest("bad doc format: need one of 'text', 'md', 'markdown' or 'html'")
	}

	um, err := resolveModulePath(r, ds, pkgPath, params.Module, params.Version)
	if err != nil {
		return err
	}

	fs := internal.WithMain
	if params.Licenses {
		fs |= internal.WithLicenses
	}
	if params.Imports {
		fs |= internal.WithImports
	}
	if params.Doc != "" || params.Examples {
		fs |= internal.WithDocsSource
	}

	bc := internal.BuildContext{GOOS: params.GOOS, GOARCH: params.GOARCH}
	unit, err := ds.GetUnit(r.Context(), um, fs, bc)
	if err != nil {
		return err
	}

	// api:response Package
	resp, err := unitToPackage(unit, params)
	if err != nil {
		return err
	}

	return serveJSON(w, http.StatusOK, resp, versionCacheDur(params.Version))
}

// ServeModule handles requests for the v1beta module metadata endpoint.
// api:route /v1beta/module/{path}
// api:desc Information about the module at {path}.
// api:example /v1beta/module/golang.org/x/time
func ServeModule(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
	defer derrors.Wrap(&err, "ServeModule")

	modulePath := trimPath(r, "/v1beta/module/")
	if modulePath == "" {
		return BadRequest("missing module path",
			"the module path must be provided after '/module/'")
	}

	// api:params ModuleParams
	var params ModuleParams
	if err := ParseParams(r.URL.Query(), &params); err != nil {
		return err
	}

	requestedVersion := params.Version
	if requestedVersion == "" {
		requestedVersion = version.Latest
	}
	// The served response is cacheDur if and only if the version is.
	cacheDur := versionCacheDur(requestedVersion)

	// For modules, we can use GetUnitMeta on the module path.
	um, err := ds.GetUnitMeta(r.Context(), modulePath, internal.UnknownModulePath, requestedVersion)
	if err != nil {
		return err
	}

	if err := checkModulePath(modulePath, um.ModulePath); err != nil {
		return err
	}

	// api:response Module
	resp := Module{
		Path:              um.ModulePath,
		Version:           um.Version,
		CommitTime:        um.CommitTime,
		IsLatest:          um.Version == um.LatestVersion,
		IsStandardLibrary: stdlib.Contains(um.ModulePath),
		IsRedistributable: um.IsRedistributable,
		HasGoMod:          um.HasGoMod,
	}
	// RepoURL needs to be extracted from source info if available
	if um.SourceInfo != nil {
		resp.RepoURL = um.SourceInfo.RepoURL()
	}

	if !params.Readme && !params.Licenses {
		return serveJSON(w, http.StatusOK, resp, cacheDur)
	}

	fs := internal.MinimalFields
	if params.Readme {
		fs |= internal.WithMain // WithMain includes Readme in GetUnit
	}
	if params.Licenses {
		fs |= internal.WithLicenses
	}
	unit, err := ds.GetUnit(r.Context(), um, fs, internal.BuildContext{})
	if err != nil {
		return serveJSON(w, http.StatusOK, resp, cacheDur)
	}

	if params.Readme && unit.Readme != nil {
		resp.Readme = &Readme{
			Filepath: unit.Readme.Filepath,
			Contents: unit.Readme.Contents,
		}
	}
	if params.Licenses {
		for _, l := range unit.LicenseContents {
			resp.Licenses = append(resp.Licenses, License{
				Types:    l.Metadata.Types,
				FilePath: l.Metadata.FilePath,
				Contents: string(l.Contents),
			})
		}
	}

	return serveJSON(w, http.StatusOK, resp, cacheDur)
}

// ServeModuleVersions handles requests for the v1beta module versions endpoint.
// api:route /v1beta/versions/{path}
// api:desc Versions of the module at {path}.
// api:desc If there are tagged versions, they are returned.
// api:desc Otherwise, the 10 most recent pseudo-versions are returned.
// api:desc The versions are in descending order.
// api:desc Only results that match the filter query parameter are returned.
// api:example /v1beta/versions/golang.org/x/time?limit=3
func ServeModuleVersions(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
	defer derrors.Wrap(&err, "ServeModuleVersions")

	path := trimPath(r, "/v1beta/versions/")
	if path == "" {
		return BadRequest("missing module path",
			"the module path must be provided after '/versions/'")
	}

	// api:params VersionsParams
	var params VersionsParams
	if err := ParseParams(r.URL.Query(), &params); err != nil {
		return err
	}
	um, err := ds.GetUnitMeta(r.Context(), path, internal.UnknownModulePath, version.Latest)
	if err != nil {
		return fmt.Errorf("module %q: %w", path, err)
	}
	if err := checkModulePath(path, um.ModulePath); err != nil {
		return err
	}

	infos, err := ds.GetVersionsForPath(r.Context(), path)
	if err != nil {
		return err
	}
	var mvs []ModuleVersion
	for _, in := range infos {
		mvs = append(mvs, ModuleVersion{
			ModulePath:        in.ModulePath,
			Version:           in.Version,
			CommitTime:        in.CommitTime,
			IsRedistributable: in.IsRedistributable,
			HasGoMod:          in.HasGoMod,
			LatestVersion:     in.LatestVersion,
			Deprecated:        in.Deprecated,
			DeprecationReason: in.DeprecationComment,
			Retracted:         in.Retracted,
			RetractionReason:  in.RetractionRationale,
		})
	}
	mvs, err = filterStruct(mvs, params.Filter)
	if err != nil {
		return err
	}

	// api:response PaginatedResponse[ModuleVersion]
	resp, err := paginate(mvs, params.ListParams, defaultLimit)
	if err != nil {
		return err
	}

	// The response is never immutable, because a new version can arrive at any time.
	return serveJSON(w, http.StatusOK, resp, shortCacheDur)
}

// ServeModulePackages handles requests for the v1beta module packages endpoint.
// api:route /v1beta/packages/{path}
// api:desc Information about packages of the module at {path}.
// api:desc Filtering is applied to the list of packages in the response.
// api:desc Only packages that match the filter query parameter are returned.
// api:example /v1beta/packages/golang.org/x/time/rate
func ServeModulePackages(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
	defer derrors.Wrap(&err, "ServeModulePackages")

	modulePath := trimPath(r, "/v1beta/packages/")
	if modulePath == "" {
		return BadRequest("missing module path",
			"the module path must be provided after '/packages/'")
	}

	// api:params PackagesParams
	var params PackagesParams
	if err := ParseParams(r.URL.Query(), &params); err != nil {
		return err
	}

	requestedVersion := params.Version
	if requestedVersion == "" {
		requestedVersion = version.Latest
	}

	// Resolve latest version, and check if specific version exists.
	um, err := ds.GetUnitMeta(r.Context(), modulePath, internal.UnknownModulePath, requestedVersion)
	if err != nil {
		return err
	}

	if err := checkModulePath(modulePath, um.ModulePath); err != nil {
		return err
	}

	metas, err := ds.GetModulePackages(r.Context(), um.ModulePath, um.Version)
	if err != nil {
		return err
	}

	var pinfos []PackageInfo
	for _, m := range metas {
		pinfos = append(pinfos, PackageInfo{
			Path:              m.Path,
			Name:              m.Name,
			Synopsis:          m.Synopsis,
			IsRedistributable: m.IsRedistributable,
		})
	}
	pinfos, err = filterStruct(pinfos, params.Filter)
	if err != nil {
		return err
	}

	// api:response PackagesResponse
	resp := PackagesResponse{
		ModulePath:        um.ModulePath,
		Version:           um.Version,
		IsStandardLibrary: stdlib.Contains(modulePath),
	}

	resp.Packages, err = paginate(pinfos, params.ListParams, defaultLimit)
	if err != nil {
		return err
	}

	return serveJSON(w, http.StatusOK, resp, versionCacheDur(requestedVersion))
}

// ServeSearch handles requests for the v1 search endpoint.
// api:route /v1beta/search
// api:desc Search results. Only results that match the filter query parameter are returned.
// api:desc Results are sorted by how well the match the query, with the best match first.
// api:example /v1beta/search?q=xyzzy
func ServeSearch(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
	defer derrors.Wrap(&err, "ServeSearch")

	// api:params SearchParams
	var params SearchParams
	if err := ParseParams(r.URL.Query(), &params); err != nil {
		return err
	}

	if params.Query == "" {
		return BadRequest("missing query", "provide the query by using the query parameter 'q'")
	}

	dbLimit := maxSearchResults
	// We can only optimize the DB limit when no filter is present.
	// Filtering is done in memory after fetching results, so we need a large
	// candidate set to avoid returning empty pages when matches exist further down.
	if params.Filter == "" {
		limit, offset, err := params.ListParams.pageParams(defaultSearchLimit)
		if err != nil {
			return fmt.Errorf("%w: %s", derrors.InvalidArgument, err.Error())
		}
		dbLimit = min(offset+limit+1, maxSearchResults)
	}

	dbresults, err := ds.Search(r.Context(), params.Query, internal.SearchOptions{
		MaxResults:     dbLimit,
		MaxResultCount: maxSearchResults,
		SearchSymbols:  params.Symbol != "",
		SymbolFilter:   params.Symbol,
		// Don't group search results: packages in the same module and
		// in modules with different major versions will all appear in
		// the same flat list, sorted by score.
		GroupResults: false,
	})
	if err != nil {
		return err
	}

	var results []SearchResult
	for _, r := range dbresults {
		results = append(results, SearchResult{
			PackagePath: r.PackagePath,
			ModulePath:  r.ModulePath,
			Version:     r.Version,
			Synopsis:    r.Synopsis,
		})
	}

	results, err = filterStruct(results, params.Filter)
	if err != nil {
		return err
	}

	// api:response PaginatedResponse[SearchResult]
	resp, err := paginate(results, params.ListParams, defaultLimit)
	if err != nil {
		return fmt.Errorf("%w: %s", derrors.InvalidArgument, err.Error())
	}
	if params.Filter == "" && len(dbresults) > 0 {
		resp.Total = int(dbresults[0].NumResults)
	}

	// Search results are never immutable, because new modules are always being added.
	// NOTE: the default cache freshness is set to 1 hour (see serveJSON). This seems
	// like a reasonable time to cache a search, but be aware of complaints
	// about stale search results.
	return serveJSON(w, http.StatusOK, resp, shortCacheDur)
}

// ServePackageSymbols handles requests for the v1beta package symbols endpoint.
// api:route /v1beta/symbols/{path}
// api:desc List of symbols for the package at {path}.
// api:desc Filtering is applied to the list of symbols in the response.
// api:desc Only symbols that match the filter query parameter are returned.
// api:example /v1beta/symbols/golang.org/x/time/rate
func ServePackageSymbols(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
	defer derrors.Wrap(&err, "ServePackageSymbols")

	pkgPath := trimPath(r, "/v1beta/symbols/")
	if pkgPath == "" {
		return BadRequest("missing package path",
			"the package path must be provided after '/symbols/'")
	}

	// api:params SymbolsParams
	var params SymbolsParams
	if err := ParseParams(r.URL.Query(), &params); err != nil {
		return err
	}

	um, err := resolveModulePath(r, ds, pkgPath, params.Module, params.Version)
	if err != nil {
		return err
	}

	bc := internal.BuildContext{GOOS: params.GOOS, GOARCH: params.GOARCH}
	dbSyms, err := ds.GetSymbols(r.Context(), pkgPath, um.ModulePath, um.Version, bc)
	if err != nil {
		return fmt.Errorf("symbols for package %s: %w", pkgPath, err)
	}

	var syms []*internal.Symbol
	for _, s := range dbSyms {
		syms = append(syms, s)
		for _, child := range s.Children {
			syms = append(syms, &internal.Symbol{
				SymbolMeta: *child,
				GOOS:       s.GOOS,
				GOARCH:     s.GOARCH,
			})
		}
		s.Children = nil
	}

	syms = slices.Clone(syms)

	// TODO(jba): combine this loop with the one above, if possible.
	var items []Symbol
	for _, s := range syms {
		items = append(items, Symbol{
			Name:     s.Name,
			Kind:     string(s.Kind),
			Synopsis: s.Synopsis,
			Parent:   s.ParentName,
		})
	}

	items, err = filterStruct(items, params.Filter)
	if err != nil {
		return err
	}

	paged, err := paginate(items, params.ListParams, defaultLimit)
	if err != nil {
		return err
	}
	// api:response PackageSymbols
	resp := PackageSymbols{
		ModulePath: um.ModulePath,
		Version:    um.Version,
		Symbols:    paged,
	}

	return serveJSON(w, http.StatusOK, resp, versionCacheDur(params.Version))
}

// ServePackageImportedBy handles requests for the v1beta package imported-by endpoint.
// api:route /v1beta/imported-by/{path}
// api:desc Paths of packages importing the package at {path},
// api:desc not including packages in the same module.
// api:desc Filtering is applied to the list of paths in the response.
// api:desc Only paths that match the filter query parameter are returned.
// api:desc Within a filter, the variable `path` is set to the import path.
// api:example /v1beta/imported-by/golang.org/x/time/rate?limit=10&filter=%5E.%2A%5C.io%2F
func ServePackageImportedBy(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
	defer derrors.Wrap(&err, "ServePackageImportedBy")

	pkgPath := trimPath(r, "/v1beta/imported-by/")
	if pkgPath == "" {
		return BadRequest("missing package path",
			"the package path must be provided after '/imported-by/'")
	}

	// api:params ImportedByParams
	var params ImportedByParams
	if err := ParseParams(r.URL.Query(), &params); err != nil {
		return err
	}

	requestedVersion := params.Version
	if requestedVersion == "" {
		requestedVersion = version.Latest
	}

	um, err := resolveModulePath(r, ds, pkgPath, params.Module, requestedVersion)
	if err != nil {
		return err
	}
	modulePath := um.ModulePath

	limit := params.Limit
	// If the user doesn't provide a limit, use a default.
	if limit <= 0 {
		limit = defaultLimit
	}
	// Cap the user-supplied limit so we don't do too much work.
	if limit > maxLimit {
		limit = maxLimit
	}

	// Resolve start path from token
	start := ""
	if params.Token != "" {
		var err error
		start, err = decodeStringPageToken(params.Token)
		if err != nil {
			return BadRequest(fmt.Sprintf("invalid next-page token: %v", err), "try again from the beginning, with no token")
		}
	}

	// Fetch an extra item so we can tell if we're done.
	importedBy, err := ds.GetImportedBy(r.Context(), pkgPath, modulePath, start, limit+1)
	if err != nil {
		return err
	}

	nextToken := ""
	if len(importedBy) > limit {
		if len(importedBy) != limit+1 {
			return InternalServerError("len(importedBy)=%d, expected %d", len(importedBy), limit+1)
		}

		nextToken, err = encodeStringPageToken(importedBy[limit])
		if err != nil {
			return err
		}
		importedBy = importedBy[:limit]
	}

	count, err := ds.GetImportedByCount(r.Context(), pkgPath, modulePath)
	if err != nil {
		return err
	}

	filtered, err := filterString(importedBy, params.Filter, "path")
	if err != nil {
		return err
	}
	// len(filtered) may be 0. That's fine: we document that zero-length
	// pages are OK.
	// The alternative is to fetch rows indefinitely, which means unbounded
	// work.

	// api:response PackageImportedBy
	resp := PackageImportedBy{
		ModulePath: modulePath,
		Version:    requestedVersion,
		ImportedBy: PaginatedResponse[string]{
			Items:         filtered,
			Total:         count,
			NextPageToken: nextToken,
		},
	}

	// The imported-by list is not immutable, because new modules are always being added.
	return serveJSON(w, http.StatusOK, resp, shortCacheDur)
}

// ServeVulnerabilities handles requests for the v1beta vulnerabilities endpoint.
// api:route /v1beta/vulns/{path}
// api:desc Vulnerabilities of the module or package at {path}, from
// api:desc the Go vulnerability database (https://vuln.go.dev).
// api:desc Only results that match the filter query parameter are returned.
// api:example /v1beta/vulns/golang.org/x/image
func ServeVulnerabilities(vc *vuln.Client) func(w http.ResponseWriter, r *http.Request, _ internal.DataSource) error {
	return func(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
		defer derrors.Wrap(&err, "ServeVulnerabilities")

		path := trimPath(r, "/v1beta/vulns/")
		if path == "" {
			return BadRequest("missing path",
				"the package or module path must be provided after '/vulns/'")
		}

		// api:params VulnParams
		var params VulnParams
		if err := ParseParams(r.URL.Query(), &params); err != nil {
			return err
		}

		if vc == nil {
			return InternalServerError("vulnerability client is nil")
		}

		requestedVersion := params.Version
		if requestedVersion == "" {
			requestedVersion = version.Latest
		}

		// Verify package or module existence and resolve containing module.
		um, err := resolveModulePath(r, ds, path, params.Module, requestedVersion)
		if err != nil {
			return err
		}

		var pkgPath string
		if path != um.ModulePath {
			pkgPath = path
		}

		// Use VulnsForPackage from internal/vuln to get vulnerabilities.
		// If pkgPath is non-empty, it filters vulnerabilities to only that package.
		vulns := vuln.VulnsForPackage(r.Context(), um.ModulePath, um.Version, pkgPath, vc)

		vulns, err = filterStruct(vulns, params.Filter)
		if err != nil {
			return err
		}

		var items []Vulnerability
		for _, v := range vulns {
			items = append(items, Vulnerability{
				ID:      v.ID,
				Details: v.Details,
			})
		}

		// api:response PaginatedResponse[Vulnerability]
		resp, err := paginate(items, params.ListParams, defaultLimit)
		if err != nil {
			return err
		}

		return serveJSON(w, http.StatusOK, resp, versionCacheDur(requestedVersion))
	}
}

func trimPath(r *http.Request, prefix string) string {
	path := strings.TrimPrefix(r.URL.Path, prefix)
	return strings.Trim(path, "/")
}

// resolveModulePath determines the correct module path for a given package path and version.
// If the module path is not provided, it searches through potential candidate module paths
// derived from the package path.
//
// Resolution logic:
//  1. Use internal.CandidateModulePaths(pkgPath) to get potential candidates (ordered longest first).
//  2. Fetch UnitMeta for each candidate that exists in the data source.
//  3. Check if um.ModulePath == mp (where mp is the candidate module path). If not, ignore it
//     (this handles the case where GetUnitMeta falls back to another module when the requested
//     module does not exist).
//  4. Filter candidates by eliminating those that are deprecated or retracted.
//  5. If exactly one candidate remains after filtering, return it (HTTP 200).
//  6. If multiple candidates remain, return HTTP 400 with the list of candidates (ambiguity).
//  7. If all candidates are eliminated (e.g., all are deprecated or retracted), fall back to
//     the longest matching candidate among those that exist (HTTP 200).
func resolveModulePath(r *http.Request, ds internal.DataSource, pkgPath, modulePath, requestedVersion string) (*internal.UnitMeta, error) {
	if requestedVersion == "" {
		requestedVersion = version.Latest
	}
	if modulePath != "" {
		um, err := ds.GetUnitMeta(r.Context(), pkgPath, modulePath, requestedVersion)
		if err != nil {
			return nil, err
		}
		return um, nil
	}

	candidates := internal.CandidateModulePaths(pkgPath)
	var validCandidates []*internal.UnitMeta
	for _, mp := range candidates {
		if um, err := ds.GetUnitMeta(r.Context(), pkgPath, mp, requestedVersion); err == nil {
			// Critical check: ensure the DB actually found the candidate module we requested.
			// GetUnitMeta falls back to the best match if the requested module doesn't exist,
			// which could lead to false positives (e.g. google.golang.org matching because it
			// falls back to google.golang.org/adk/agent).
			if um.ModulePath == mp {
				validCandidates = append(validCandidates, um)
			}
		} else if !errors.Is(err, derrors.NotFound) {
			return nil, err
		}
	}

	if len(validCandidates) == 0 {
		return nil, derrors.NotFound
	}

	// Filter candidates based on signals (deprecation, retraction).
	goodCandidates := slices.Clone(validCandidates)
	goodCandidates = slices.DeleteFunc(goodCandidates, func(um *internal.UnitMeta) bool {
		return um.Deprecated || um.Retracted
	})

	switch len(goodCandidates) {
	case 1:
		return goodCandidates[0], nil
	case 0:
		// If all candidates are deprecated or retracted, fall back to the longest match.
		// Since candidates are ordered longest first, validCandidates[0] is the longest match.
		return validCandidates[0], nil
	default:
		return nil, &Error{
			Code:       http.StatusBadRequest,
			Message:    "ambiguous package path",
			Fixes:      []string{"retry the call with a 'module' query parameter specifying the desired module"},
			Candidates: makeCandidates(goodCandidates),
		}
	}
}

func makeCandidates(ums []*internal.UnitMeta) []Candidate {
	var r []Candidate
	for _, um := range ums {
		r = append(r, Candidate{
			ModulePath:  um.ModulePath,
			PackagePath: um.Path,
		})
	}
	return r
}

// Values for the Cache-Control header.
// Compare with the TTLs for pkgsite's own cache, in internal/frontend/server.go
// (look for symbols ending in "TTL").
// Those values are shorter to manage our cache's memory, but the job of
// Cache-Control is to reduce network traffic; downstream caches can manage
// their own memory.
const (
	// Immutable pages can theoretically, be cached indefinitely,
	// but have them time out so that excluded modules don't
	// live in caches forever.
	longCacheDur = 3 * time.Hour
	// The information on some pages can change relatively quickly.
	shortCacheDur = 1 * time.Hour
	// Errors should not be cached.
	noCache = time.Duration(0)
)

func serveJSON(w http.ResponseWriter, status int, data any, cacheDur time.Duration) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(data); err != nil {
		return err
	}
	w.Header().Set("Content-Type", "application/json")
	var ccHeader string
	if cacheDur == 0 {
		ccHeader = "no-store"
	} else {
		ccHeader = fmt.Sprintf("public, max-age=%d", int(cacheDur.Seconds()))
	}
	w.Header().Set("Cache-Control", ccHeader)
	w.WriteHeader(status)
	_, err := w.Write(buf.Bytes())
	return err
}

func ServeError(w http.ResponseWriter, r *http.Request, err error) error {
	var aerr *Error
	if !errors.As(err, &aerr) {
		status := derrors.ToStatus(err)
		aerr = &Error{
			Code:    status,
			Message: strings.ToLower(http.StatusText(status)),
			err:     err,
		}
	}
	log.Errorf(r.Context(), "API error %d: %v", aerr.Code, aerr)
	return serveJSON(w, aerr.Code, aerr, noCache)
}

// paginate returns a paginated response for the given list of items and pagination parameters.
// It uses offset-based pagination with a token that encodes the offset.
// The default limit is used if the provided limit is non-positive.
func paginate[T any](all []T, lp ListParams, defaultLimit int) (PaginatedResponse[T], error) {
	limit, offset, err := lp.pageParams(defaultLimit)
	if err != nil {
		return PaginatedResponse[T]{}, fmt.Errorf("%w: %s", derrors.InvalidArgument, err)
	}

	offset = min(offset, len(all))
	end := min(offset+limit, len(all))

	var nextToken string
	if end < len(all) {
		var err error
		nextToken, err = encodePageToken(end)
		if err != nil {
			return PaginatedResponse[T]{}, fmt.Errorf("encoding token: %w", err)
		}
	}

	return PaginatedResponse[T]{
		Items:         all[offset:end],
		Total:         len(all),
		NextPageToken: nextToken,
	}, nil
}

// unitToPackage processes unit documentation into a Package struct.
func unitToPackage(unit *internal.Unit, params PackageParams) (*Package, error) {
	// Although unit.Documentation is a slice, it will
	// have at most one item, the documentation matching
	// the build context.
	synopsis := ""
	var docs string
	goos := params.GOOS
	goarch := params.GOARCH
	if len(unit.Documentation) > 0 {
		d := unit.Documentation[0]
		synopsis = d.Synopsis
		// Return the more precise GOOS/GOARCH.
		// If the user didn't provide them, use the unit's.
		// If the user did, assume what they provided is at
		// least as specific as the unit's, and use it.
		if goos == "" {
			goos = d.GOOS
		}
		if goarch == "" {
			goarch = d.GOARCH
		}
		if params.Doc != "" {
			var err error
			docs, err = renderDocumentation(unit, d, params.Doc, params.Examples)
			if err != nil {
				return nil, err
			}
		}
	}

	var licenses []License
	for _, l := range unit.LicenseContents {
		licenses = append(licenses, License{
			Types:    l.Metadata.Types,
			FilePath: l.Metadata.FilePath,
			Contents: string(l.Contents),
		})
	}

	return &Package{
		ModulePath:        unit.ModulePath,
		Version:           unit.Version,
		IsStandardLibrary: stdlib.Contains(unit.ModulePath),
		IsLatest:          unit.Version == unit.LatestVersion,
		GOOS:              goos,
		GOARCH:            goarch,
		Docs:              docs,
		Imports:           unit.Imports,
		Licenses:          licenses,
		PackageInfo: PackageInfo{
			Path:              unit.Path,
			Name:              unit.Name,
			IsRedistributable: unit.IsRedistributable,
			Synopsis:          synopsis,
		},
	}, nil
}

// renderDocumentation renders the provided unit into the specified format.
func renderDocumentation(unit *internal.Unit, d *internal.Documentation, format string, examples bool) (string, error) {
	// d.Source is an encoded AST. Decode it, then use
	// go/doc (not pkgsite's renderer) to generate the
	// result.
	gpkg, err := godoc.DecodePackage(d.Source)
	if err != nil {
		return "", fmt.Errorf("renderDocumentation: %w", err)
	}
	innerPath := internal.Suffix(unit.Path, unit.ModulePath)
	modInfo := &godoc.ModuleInfo{ModulePath: unit.ModulePath, ResolvedVersion: unit.Version}
	dpkg, err := gpkg.DocPackage(innerPath, modInfo)
	if err != nil {
		return "", err
	}
	var r renderer
	var sb strings.Builder
	switch format {
	case "text":
		r = newTextRenderer(gpkg.Fset, &sb)
	case "md", "markdown":
		r = newMarkdownRenderer(gpkg.Fset, &sb)
	case "html":
		r = newHTMLRenderer(gpkg.Fset, &sb)
	default:
		// ServePackage needs to be updated when the doc set changes.
		return "", BadRequest("bad doc format: need one of 'text', 'md', 'markdown' or 'html'")
	}
	if err := renderDoc(dpkg, r, examples); err != nil {
		return "", fmt.Errorf("renderDoc: %w", err)
	}
	return sb.String(), nil
}

// versionCacheDur returns the duration used in the Cache-Control header
// appropriate for the given module version.
func versionCacheDur(v string) time.Duration {
	immutable := !(v == "" || v == version.Latest || internal.DefaultBranches[v] || stdlib.SupportedBranches[v])
	if immutable {
		return longCacheDur
	}
	return shortCacheDur
}

// filter returns a new slice containing all elements in list which match
// the expression denoted by filter.
// It sets each element to varName before evaluating the filter.
func filterString(list []string, filter, varName string) ([]string, error) {
	if varName == "" {
		return nil, errors.New("string filter must have varName")
	}
	if filter == "" {
		return list, nil
	}
	return filterInternal(list, filter, nil, varName)
}

// filter returns a new slice containing all elements in list which match
// the expression denoted by filter.
func filterStruct[T any](list []T, filter string) ([]T, error) {
	if filter == "" {
		return list, nil
	}
	t := reflect.TypeFor[T]()
	for t.Kind() == reflect.Pointer {
		t = t.Elem()
	}
	if t.Kind() != reflect.Struct {
		return nil, fmt.Errorf("bad type %s for filter: need struct or pointer to struct", t)
	}
	return filterInternal(list, filter, jsonFields(t), "")
}

func filterInternal[T any](list []T, filter string, jfields fieldMap, varName string) ([]T, error) {
	expr, err := parser.ParseExpr(filter)
	if err != nil {
		return nil, BadRequest(fmt.Sprintf(`parsing filter "%s": %v`,
			filter, err),
			"the 'filter' query parameter must be a valid Go expression; see the documentation at /v1beta/api",
		)
	}
	var out []T
	for _, e := range list {
		env := maps.Clone(defaultEnv)
		if jfields == nil {
			env[varName] = e
		} else {
			tv := reflect.ValueOf(e)
			if !tv.IsValid() {
				continue
			}
			for tv.Kind() == reflect.Pointer {
				tv = tv.Elem()
			}
			for name, field := range jfields {
				env[name] = tv.FieldByIndex(field.Index).Interface()
			}
		}
		res, err := evaluate(expr, env)
		if err != nil {
			return nil, BadRequest(fmt.Sprintf(`evaluating filter "%s": %v`, filter, err),
				"the filter must be a Go expression; see the documentation at /v1beta/api")
		}
		b, ok := res.(bool)
		if !ok {
			return nil, BadRequest(fmt.Sprintf(`filter "%s" did not evaluate to bool`, filter),
				"the filter must be a boolean Go expression; see the documentation at /v1beta/api")
		}
		if b {
			out = append(out, e)
		}
	}
	return out, nil
}

// checkModulePath verifies that the requested module path exactly matches the resolved
// module path. If it is a package path instead, it returns a BadRequest error with
// containing module suggestions.
func checkModulePath(requested, resolved string) error {
	if requested != resolved {
		return &Error{
			Code:    http.StatusBadRequest,
			Message: fmt.Sprintf("%s is a package, not a module", requested),
			Fixes:   []string{fmt.Sprintf("retry the call with the containing module: %q", resolved)},
		}
	}
	return nil
}
