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

// Command pkgsite-cli queries the pkg.go.dev API for information about
// Go packages and modules.
//
// For more information, see https://go.dev/blog/pkgsite-api.
//
// Usage:
//
//	pkgsite-cli package <package>[@version] [flags]    Show package details.
//	pkgsite-cli module <module>[@version] [flags]      Show module details.
//	pkgsite-cli search <query> [flags]                 Search for packages.
package main

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/pkgsite/cmd/internal/pkgsite-cli/client"
	"golang.org/x/telemetry"
)

func main() {
	cfg := telemetry.Config{
		ReportCrashes: true,
	}
	telemetry.Start(cfg)

	os.Exit(run(os.Args[1:], os.Stdout, os.Stderr))
}

func run(args []string, stdout, stderr io.Writer) int {
	return dispatch(args, commands(), stdout, stderr)
}

func commands() []*command {
	var pf packageFlags
	pkgFS := flag.NewFlagSet(filepath.Base(os.Args[0]), flag.ContinueOnError)
	pf.register(pkgFS)

	var mf moduleFlags
	modFS := flag.NewFlagSet(filepath.Base(os.Args[0])+" module", flag.ContinueOnError)
	mf.register(modFS)

	var sf searchFlags
	searchFS := flag.NewFlagSet(filepath.Base(os.Args[0])+" search", flag.ContinueOnError)
	sf.register(searchFS)

	pkgRun := func(fs *flag.FlagSet, stdout, stderr io.Writer) int { return runPackage(fs, &pf, stdout, stderr) }

	const packageDoc = `Queries information about a specific Go package from pkg.go.dev.
By default, this prints basic metadata. Use flags to request additional
information such as exported symbols, reverse dependencies, or rendered documentation.

When using -json, the output is a JSON object with the following structure:

    type packageResult struct {
        Package    *Package                          // package information
        Symbols    *PaginatedResponse[Symbol]        // symbols (with -symbols)
        ImportedBy *PackageImportedBy                // reverse dependencies (with -imported-by)
    }

    type Package struct {
        Path              string
        Name              string
        Synopsis          string
        IsRedistributable bool
        ModulePath        string
        Version           string
        IsLatest          bool
        IsStandardLibrary bool
        GOOS              string
        GOARCH            string
        Docs              string    // rendered documentation (with -doc)
        Imports           []string  // imports (with -imports)
        Licenses          []License // licenses (with -licenses)
    }

    type License struct {
        Types    []string
        FilePath string
    }
`

	const moduleDoc = `Queries information about a specific Go module from pkg.go.dev.
By default, this prints basic metadata. Use flags to request additional
information such as versions, vulnerabilities, or packages contained in the module.

When using -json, the output is a JSON object with the following structure:

    type moduleResult struct {
        Module   *Module                                   // module information
        Versions *PaginatedResponse[VersionResponse]       // versions (with -versions)
        Vulns    *PaginatedResponse[Vulnerability]         // vulnerabilities (with -vulns)
        Packages *PaginatedResponse[ModulePackageResponse] // packages (with -packages)
    }

    type Module struct {
        Path              string
        Version           string
        CommitTime        time.Time
        IsLatest          bool
        IsRedistributable bool
        IsStandardLibrary bool
        HasGoMod          bool
        RepoURL           string
        GoModContents     string
        Readme            *Readme
        Licenses          []License
    }
`

	const searchDoc = `Searches for Go packages on pkg.go.dev matching the given query.
By default, this prints a list of matching packages with their synopsis.

When using -json, the output is a JSON object with the following structure:

    type PaginatedResponse[SearchResult] struct {
        Items         []SearchResult
        Total         int
        NextPageToken string
    }

    type SearchResult struct {
        PackagePath string
        ModulePath  string
        Version     string
        Synopsis    string
    }
`

	var cmds []*command
	cmds = []*command{
		{
			name:        "package",
			args:        "<package>[@version]",
			summary:     "Show package details",
			description: strings.TrimSpace(packageDoc),
			flags:       pkgFS,
			run:         pkgRun,
		},
		{
			name:        "module",
			args:        "<module>[@version]",
			summary:     "Show module details",
			description: strings.TrimSpace(moduleDoc),
			flags:       modFS,
			run:         func(fs *flag.FlagSet, stdout, stderr io.Writer) int { return runModule(fs, &mf, stdout, stderr) },
		},
		{
			name:        "search",
			args:        "<query>",
			summary:     "Search for packages",
			description: strings.TrimSpace(searchDoc),
			flags:       searchFS,
			run:         func(fs *flag.FlagSet, stdout, stderr io.Writer) int { return runSearch(fs, &sf, stdout, stderr) },
		},
		{
			name:    "help",
			summary: "Show this help message",
			run:     func(_ *flag.FlagSet, stdout, _ io.Writer) int { printUsage(stdout, cmds); return 0 },
		},
		{
			name:    "version",
			summary: "Print version information",
			run:     func(_ *flag.FlagSet, stdout, _ io.Writer) int { fmt.Fprintln(stdout, versionInfo()); return 0 },
		},
	}
	return cmds
}

// splitPathVersion splits "path@version" into its components.
// If there is no @, version is empty.
func splitPathVersion(s string) (path, version string) {
	path, version, _ = strings.Cut(s, "@")
	return path, version
}

// handleErr writes an error message. In JSON mode, the error is written
// to stdout as a JSON object so callers can parse it. In text mode, it
// goes to stderr.
func handleErr(stdout, stderr io.Writer, err error, jsonMode bool) {
	if jsonMode {
		aerr, ok := err.(*client.Error)
		if !ok {
			aerr = &client.Error{Code: 1, Message: err.Error()}
		}
		if errors.Is(err, context.DeadlineExceeded) {
			aerr.Message = "request timed out"
			aerr.Fixes = []string{"use the -timeout flag to increase the timeout", "reduce size of request by limiting items returned"}
		}
		writeJSON(stdout, stderr, aerr)
		return
	}
	if errors.Is(err, context.DeadlineExceeded) {
		fmt.Fprintln(stderr, "Error: request timed out; use the -timeout flag to increase it")
	} else {
		fmt.Fprintln(stderr, err)
	}
}

func writeJSON(stdout, stderr io.Writer, v any) int {
	enc := json.NewEncoder(stdout)
	enc.SetIndent("", "  ")
	if err := enc.Encode(v); err != nil {
		fmt.Fprintln(stderr, err)
		return 1
	}
	return 0
}
