// Copyright 2020 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 metrics_test

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/doc"
	"go/doc/comment"
	"go/format"
	"go/parser"
	"go/token"
	"internal/diff"
	"os"
	"regexp"
	"runtime/metrics"
	"slices"
	"strings"
	"testing"
	_ "unsafe"
)

// Implemented in the runtime.
//
//go:linkname runtime_readMetricNames
func runtime_readMetricNames() []string

func TestNames(t *testing.T) {
	// Note that this regexp is promised in the package docs for Description. Do not change.
	r := regexp.MustCompile("^(?P<name>/[^:]+):(?P<unit>[^:*/]+(?:[*/][^:*/]+)*)$")
	all := metrics.All()
	for i, d := range all {
		if !r.MatchString(d.Name) {
			t.Errorf("name %q does not match regexp %#q", d.Name, r)
		}
		if i > 0 && all[i-1].Name >= all[i].Name {
			t.Fatalf("allDesc not sorted: %s ≥ %s", all[i-1].Name, all[i].Name)
		}
	}

	names := runtime_readMetricNames()
	slices.Sort(names)
	samples := make([]metrics.Sample, len(names))
	for i, name := range names {
		samples[i].Name = name
	}
	metrics.Read(samples)

	for _, d := range all {
		for len(samples) > 0 && samples[0].Name < d.Name {
			t.Errorf("%s: reported by runtime but not listed in All", samples[0].Name)
			samples = samples[1:]
		}
		if len(samples) == 0 || d.Name < samples[0].Name {
			t.Errorf("%s: listed in All but not reported by runtime", d.Name)
			continue
		}
		if samples[0].Value.Kind() != d.Kind {
			t.Errorf("%s: runtime reports %v but All reports %v", d.Name, samples[0].Value.Kind(), d.Kind)
		}
		samples = samples[1:]
	}
}

func wrap(prefix, text string, width int) string {
	doc := &comment.Doc{Content: []comment.Block{&comment.Paragraph{Text: []comment.Text{comment.Plain(text)}}}}
	pr := &comment.Printer{TextPrefix: prefix, TextWidth: width}
	return string(pr.Text(doc))
}

func formatDesc(t *testing.T) string {
	var b strings.Builder
	for i, d := range metrics.All() {
		if i > 0 {
			fmt.Fprintf(&b, "\n")
		}
		fmt.Fprintf(&b, "%s\n", d.Name)
		fmt.Fprintf(&b, "%s", wrap("\t", d.Description, 80-2*8))
	}
	return b.String()
}

var generate = flag.Bool("generate", false, "update doc.go for go generate")

func TestDocs(t *testing.T) {
	want := formatDesc(t)

	src, err := os.ReadFile("doc.go")
	if err != nil {
		t.Fatal(err)
	}
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, "doc.go", src, parser.ParseComments)
	if err != nil {
		t.Fatal(err)
	}
	fdoc := f.Doc
	if fdoc == nil {
		t.Fatal("no doc comment in doc.go")
	}
	pkg, err := doc.NewFromFiles(fset, []*ast.File{f}, "runtime/metrics")
	if err != nil {
		t.Fatal(err)
	}
	if pkg.Doc == "" {
		t.Fatal("doc.NewFromFiles lost doc comment")
	}
	doc := new(comment.Parser).Parse(pkg.Doc)
	expectCode := false
	foundCode := false
	updated := false
	for _, block := range doc.Content {
		switch b := block.(type) {
		case *comment.Heading:
			expectCode = false
			if b.Text[0] == comment.Plain("Supported metrics") {
				expectCode = true
			}
		case *comment.Code:
			if expectCode {
				foundCode = true
				if b.Text != want {
					if !*generate {
						t.Fatalf("doc comment out of date; use go generate to rebuild\n%s", diff.Diff("old", []byte(b.Text), "want", []byte(want)))
					}
					b.Text = want
					updated = true
				}
			}
		}
	}

	if !foundCode {
		t.Fatalf("did not find Supported metrics list in doc.go")
	}
	if updated {
		fmt.Fprintf(os.Stderr, "go test -generate: writing new doc.go\n")
		var buf bytes.Buffer
		buf.Write(src[:fdoc.Pos()-f.FileStart])
		buf.WriteString("/*\n")
		buf.Write(new(comment.Printer).Comment(doc))
		buf.WriteString("*/")
		buf.Write(src[fdoc.End()-f.FileStart:])
		src, err := format.Source(buf.Bytes())
		if err != nil {
			t.Fatal(err)
		}
		if err := os.WriteFile("doc.go", src, 0666); err != nil {
			t.Fatal(err)
		}
	} else if *generate {
		fmt.Fprintf(os.Stderr, "go test -generate: doc.go already up-to-date\n")
	}
}

func TestReadEmptySlice(t *testing.T) {
	// Test that Read does not panic when given an empty slice.
	// This should be a no-op.
	metrics.Read(nil)
	metrics.Read([]metrics.Sample{})
}
