// Copyright 2023 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 task

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/http/httptest"
	"reflect"
	"runtime"
	"strings"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/google/uuid"
	"golang.org/x/build/dashboard"
	"golang.org/x/build/gerrit"
	"golang.org/x/build/internal/workflow"
	"golang.org/x/build/types"
)

var flagRunTagXTest = flag.Bool("run-tagx-test", false, "run tag x/ repo test, which is read-only and safe. Must have a Gerrit cookie in gitcookies.")

func TestSelectReposLive(t *testing.T) {
	if !*flagRunTagXTest {
		t.Skip("Not enabled by flags")
	}

	tasks := &TagXReposTasks{
		Gerrit: &RealGerritClient{
			Client: gerrit.NewClient("https://go-review.googlesource.com", gerrit.GitCookiesAuth()),
		},
	}
	ctx := &workflow.TaskContext{
		Context: context.Background(),
		Logger:  &testLogger{t, ""},
	}
	repos, err := tasks.SelectRepos(ctx)
	if err != nil {
		t.Fatal(err)
	}
	for _, r := range repos {
		t.Logf("%#v", r)
	}
}

func TestCycles(t *testing.T) {
	tests := []struct {
		repos []TagRepo
		want  []string
	}{
		{
			repos: []TagRepo{
				{Name: "text", Deps: []string{"tools"}},
				{Name: "tools", Deps: []string{"text"}},
				{Name: "sys"},
				{Name: "net", Deps: []string{"sys"}},
			},
			want: []string{
				"tools,text,tools",
				"text,tools,text",
			},
		},
		{
			repos: []TagRepo{
				{Name: "text", Deps: []string{"tools"}},
				{Name: "tools", Deps: []string{"fake"}},
				{Name: "fake", Deps: []string{"text"}},
			},
			want: []string{
				"tools,fake,text,tools",
				"text,tools,fake,text",
				"fake,text,tools,fake",
			},
		},
		{
			repos: []TagRepo{
				{Name: "text", Deps: []string{"tools"}},
				{Name: "tools", Deps: []string{"fake", "text"}},
				{Name: "fake", Deps: []string{"tools"}},
			},
			want: []string{
				"tools,text,tools",
				"text,tools,text",
				"tools,fake,tools",
				"fake,tools,fake",
			},
		},
		{
			repos: []TagRepo{
				{Name: "text", Deps: []string{"tools"}},
				{Name: "tools", Deps: []string{"fake", "text"}},
				{Name: "fake1", Deps: []string{"fake2"}},
				{Name: "fake2", Deps: []string{"tools"}},
			},
			want: []string{
				"tools,text,tools",
				"text,tools,text",
			},
		},
	}

	for _, tt := range tests {
		var repos []TagRepo
		for _, r := range tt.repos {
			repos = append(repos, TagRepo{
				Name:    r.Name,
				ModPath: r.Name,
				Deps:    r.Deps,
			})
		}
		cycles := checkCycles(repos)
		got := map[string]bool{}
		for _, cycle := range cycles {
			got[strings.Join(cycle, ",")] = true
		}
		want := map[string]bool{}
		for _, cycle := range tt.want {
			want[cycle] = true
		}

		if diff := cmp.Diff(got, want); diff != "" {
			t.Errorf("%v result unexpected: %v", tt.repos, diff)
		}
	}
}

var flagRunIsGreenLiveTest = flag.String("run-is-green-test", "", "run greenness test for repo@rev")

func TestIsGreenLive(t *testing.T) {
	if *flagRunIsGreenLiveTest == "" {
		t.Skip("no module/rev specified")
	}

	repo, rev, ok := strings.Cut(*flagRunIsGreenLiveTest, "@")
	if !ok {
		t.Fatalf("--run-is-green-test must be module@rev: %q", *flagRunIsGreenLiveTest)
	}

	tasks := &TagXReposTasks{
		Gerrit: &RealGerritClient{
			Client: gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth),
		},
		DashboardURL: "https://build.golang.org",
	}
	ctx := &workflow.TaskContext{Context: context.Background(), Logger: &testLogger{t, ""}}
	greenCommit, ok, err := tasks.findGreen(ctx, TagRepo{Name: repo, ModPath: "golang.org/x/" + repo}, rev, true)
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("module %v green: %v at rev %v", repo, ok, greenCommit)
}

func TestIsGreen(t *testing.T) {
	type revLine struct {
		goBranch        string
		goRev, toolsRev int
		pass            bool
	}
	tests := []struct {
		name         string
		rev          string
		lines        []revLine
		wantGreenRev string
	}{
		{
			name: "simple OK",
			rev:  "tools-1",
			lines: []revLine{
				{"master", 1, 1, true},
				{"release-branch.go1.19", 1, 1, true},
				{"release-branch.go1.18", 1, 1, true},
			},
			wantGreenRev: "tools-1",
		},
		{
			name: "missing release branch runs",
			rev:  "tools-1",
			lines: []revLine{
				{"master", 3, 3, true},
				{"master", 2, 2, true},
				{"release-branch.go1.19", 2, 2, true},
				{"release-branch.go1.18", 2, 2, true},
				{"master", 1, 1, true},
			},
			wantGreenRev: "tools-2",
		},
		{
			name: "succeed despite failures",
			rev:  "tools-1",
			lines: []revLine{
				{"master", 3, 1, false},
				{"master", 2, 1, true},
				{"master", 1, 1, false},
				{"release-branch.go1.19", 1, 1, true},
				{"release-branch.go1.18", 1, 1, true},
			},
			wantGreenRev: "tools-1",
		},
		{
			name: "not green yet",
			rev:  "tools-1",
			lines: []revLine{
				{"master", 3, 1, true},
				{"release-branch.go1.19", 1, 1, false},
				{"release-branch.go1.18", 1, 1, true},
			},
			wantGreenRev: "",
		},
		{
			name: "commit not registered on dashboard",
			rev:  "tools-2",
			lines: []revLine{
				{"master", 1, 1, true},
				{"release-branch.go1.19", 1, 1, true},
				{"release-branch.go1.18", 1, 1, true},
			},
			wantGreenRev: "",
		},
	}
	for _, tt := range tests {

		fakeDash := func(repo string) *types.BuildStatus {
			var builders []string
			for _, b := range dashboard.Builders {
				builders = append(builders, b.Name)
			}

			if repo == "" {
				// For the front page we only read branches.
				return &types.BuildStatus{
					Builders: builders,
					Revisions: []types.BuildRevision{
						{GoBranch: "master"},
						{GoBranch: "release-branch.go1.19"},
						{GoBranch: "release-branch.go1.18"},
					},
				}
			}
			st := &types.BuildStatus{
				Builders: builders,
			}
			for _, line := range tt.lines {
				rev := types.BuildRevision{
					Repo:       repo,
					Revision:   fmt.Sprintf("tools-%v", line.toolsRev),
					GoRevision: fmt.Sprintf("go-%v-%v", line.goBranch, line.goRev),
					Date:       time.Now().Format(time.RFC3339),
					Branch:     "master",
					GoBranch:   line.goBranch,
				}
				for _, b := range builders {
					switch b {
					case "linux-amd64":
						if line.pass {
							rev.Results = append(rev.Results, "ok")
						} else {
							rev.Results = append(rev.Results, "")
						}
					case "illumos-amd64", "plan9-arm":
						rev.Results = append(rev.Results, "fail")
					default:
						rev.Results = append(rev.Results, "ok")
					}
				}
				st.Revisions = append(st.Revisions, rev)
			}
			return st
		}
		dashServer := httptest.NewServer(fakeDashboard(fakeDash))
		t.Cleanup(dashServer.Close)

		commitsInRefs := func(commits, refs []string) map[string][]string {
			result := map[string][]string{}
			for _, commit := range commits {
				for _, ref := range refs {
					if strings.HasPrefix(commit, "go-"+strings.TrimPrefix(ref, "refs/heads/")) {
						result[commit] = append(result[commit], ref)
					}
				}
			}
			return result
		}

		tasks := &TagXReposTasks{
			Gerrit:       &isGreenGerrit{commitsInRefs: commitsInRefs},
			DashboardURL: dashServer.URL,
		}
		t.Run(tt.name, func(t *testing.T) {
			ctx := &workflow.TaskContext{Context: context.Background(), Logger: &testLogger{t, ""}}
			green, _, err := tasks.findGreen(ctx, TagRepo{
				Name:    "tools",
				ModPath: "golang.org/x/tools",
			}, tt.rev, false)
			if err != nil {
				t.Fatal(err)
			}
			if green != tt.wantGreenRev {
				t.Errorf("tools green at %q, wanted %q", green, tt.wantGreenRev)
			}
		})
	}
}

type isGreenGerrit struct {
	GerritClient
	commitsInRefs func(commits, refs []string) map[string][]string
}

func (g *isGreenGerrit) GetCommitsInRefs(ctx context.Context, project string, commits, refs []string) (map[string][]string, error) {
	return g.commitsInRefs(commits, refs), nil
}

const fakeGo = `#!/bin/bash -exu

case "$1" in
"get")
  ls go.mod go.sum >/dev/null
  for i in "${@:2}"; do
    echo -e "// pretend we've upgraded to $i" >> go.mod
    echo "$i h1:asdasd" | tr '@' ' ' >> go.sum
  done
  ;;
"mod")
  ls go.mod go.sum >/dev/null
  echo "tidied! $*" >> go.mod
  ;;
*)
  echo unexpected command $@
  exit 1
  ;;
esac
`

type tagXTestDeps struct {
	ctx       context.Context
	gerrit    *FakeGerrit
	tagXTasks *TagXReposTasks
}

func newTagXTestDeps(t *testing.T, repos ...*FakeRepo) *tagXTestDeps {
	if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
		t.Skip("Requires bash shell scripting support.")
	}

	ctx, cancel := context.WithCancel(context.Background())
	t.Cleanup(cancel)

	goServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ServeTarball("dl/go1.19.linux-amd64.tar.gz", map[string]string{
			"go/bin/go": fakeGo,
		}, w, r)
	}))
	t.Cleanup(goServer.Close)

	goRepo := NewFakeRepo(t, "go")
	go1 := goRepo.Commit(map[string]string{
		"main.go": "I'm the go command or something",
	})
	repos = append(repos, goRepo)

	fakeBuildlets := NewFakeBuildlets(t, "", nil)
	fakeGerrit := NewFakeGerrit(t, repos...)
	var builders, allOK []string
	for _, b := range dashboard.Builders {
		builders = append(builders, b.Name)
		allOK = append(allOK, "ok")
	}
	fakeDash := func(repo string) *types.BuildStatus {
		if repo == "" {
			// For the front page we only read branches.
			return &types.BuildStatus{
				Builders: builders,
				Revisions: []types.BuildRevision{
					{GoBranch: "master"},
				},
			}
		}
		for _, r := range repos {
			if repo != "golang.org/x/"+r.name {
				continue
			}
			st := &types.BuildStatus{
				Builders: builders,
			}
			for _, commit := range r.history {
				st.Revisions = append(st.Revisions, types.BuildRevision{
					Repo:       r.name,
					Revision:   commit,
					GoRevision: go1,
					Date:       time.Now().Format(time.RFC3339),
					Branch:     "master",
					GoBranch:   "master",
					Results:    allOK,
				})
			}
			return st
		}
		return nil
	}
	dashServer := httptest.NewServer(fakeDashboard(fakeDash))
	t.Cleanup(dashServer.Close)
	tasks := &TagXReposTasks{
		Gerrit:         fakeGerrit,
		GerritURL:      fakeGerrit.GerritURL(),
		CreateBuildlet: fakeBuildlets.CreateBuildlet,
		LatestGoBinaries: func(context.Context) (string, error) {
			return goServer.URL + "/dl/go1.19.linux-amd64.tar.gz", nil
		},
		DashboardURL: dashServer.URL,
	}
	return &tagXTestDeps{
		ctx:       ctx,
		gerrit:    fakeGerrit,
		tagXTasks: tasks,
	}
}

func TestTagXRepos(t *testing.T) {
	sys := NewFakeRepo(t, "sys")
	sys1 := sys.Commit(map[string]string{
		"go.mod": "module golang.org/x/sys\n",
		"go.sum": "\n",
	})
	sys.Tag("v0.1.0", sys1)
	sys2 := sys.Commit(map[string]string{
		"main.go": "package main",
	})
	mod := NewFakeRepo(t, "mod")
	mod1 := mod.Commit(map[string]string{
		"go.mod": "module golang.org/x/mod\n",
		"go.sum": "\n",
	})
	mod.Tag("v1.0.0", mod1)
	tools := NewFakeRepo(t, "tools")
	tools1 := tools.Commit(map[string]string{
		"go.mod":       "module golang.org/x/tools\nrequire golang.org/x/mod v1.0.0\ngo 1.18 // tagx:compat 1.16\nrequire golang.org/x/sys v0.1.0\n",
		"go.sum":       "\n",
		"gopls/go.mod": "module golang.org/x/tools/gopls\nrequire golang.org/x/mod v1.0.0\n",
		"gopls/go.sum": "\n",
	})
	tools.Tag("v1.1.5", tools1)

	deps := newTagXTestDeps(t, sys, mod, tools)

	wd := deps.tagXTasks.NewDefinition()
	w, err := workflow.Start(wd, map[string]interface{}{
		reviewersParam.Name: []string(nil),
	})
	if err != nil {
		t.Fatal(err)
	}
	ctx, cancel := context.WithTimeout(deps.ctx, time.Minute)
	defer cancel()
	_, err = w.Run(ctx, &verboseListener{t: t})
	if err != nil {
		t.Fatal(err)
	}

	tag, err := deps.gerrit.GetTag(ctx, "sys", "v0.2.0")
	if err != nil {
		t.Fatalf("sys should have been tagged with v0.2.0: %v", err)
	}
	if tag.Revision != sys2 {
		t.Errorf("sys v0.2.0 = %v, want %v", tag.Revision, sys2)
	}

	tags, err := deps.gerrit.ListTags(ctx, "mod")
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(tags, []string{"v1.0.0"}) {
		t.Errorf("mod has tags %v, wanted only v1.0.0", tags)
	}

	tag, err = deps.gerrit.GetTag(ctx, "tools", "v1.2.0")
	if err != nil {
		t.Fatalf("tools should have been tagged with v1.2.0: %v", err)
	}
	goMod, err := deps.gerrit.ReadFile(ctx, "tools", tag.Revision, "go.mod")
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(string(goMod), "sys@v0.2.0") || !strings.Contains(string(goMod), "mod@v1.0.0") {
		t.Errorf("tools should use sys v0.2.0 and mod v1.0.0. go.mod: %v", string(goMod))
	}
	if !strings.Contains(string(goMod), "tidied!") {
		t.Error("tools go.mod should be tidied")
	}
	goplsMod, err := deps.gerrit.ReadFile(ctx, "tools", tag.Revision, "gopls/go.mod")
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(string(goplsMod), "tidied!") || !strings.Contains(string(goplsMod), "1.16") || strings.Contains(string(goplsMod), "upgraded") {
		t.Error("gopls go.mod should be tidied with -compat 1.16, but not upgraded")
	}
}

func TestTagSingleRepo(t *testing.T) {
	mod := NewFakeRepo(t, "mod")
	mod1 := mod.Commit(map[string]string{
		"go.mod": "module golang.org/x/mod\n",
		"go.sum": "\n",
	})
	mod.Tag("v1.1.0", mod1)
	foo := NewFakeRepo(t, "foo")
	foo1 := foo.Commit(map[string]string{
		"go.mod": "module golang.org/x/foo\nrequire golang.org/x/mod v1.0.0\n",
		"go.sum": "\n",
	})
	foo.Tag("v1.1.5", foo1)
	foo.Commit(map[string]string{
		"main.go": "package main",
	})

	deps := newTagXTestDeps(t, mod, foo)

	wd := deps.tagXTasks.NewSingleDefinition()
	ctx, cancel := context.WithTimeout(deps.ctx, time.Minute)
	w, err := workflow.Start(wd, map[string]interface{}{
		"Repository name":   "foo",
		reviewersParam.Name: []string(nil),
	})
	if err != nil {
		t.Fatal(err)
	}
	defer cancel()
	_, err = w.Run(ctx, &verboseListener{t: t})
	if err != nil {
		t.Fatal(err)
	}

	tag, err := deps.gerrit.GetTag(ctx, "foo", "v1.2.0")
	if err != nil {
		t.Fatalf("foo should have been tagged with v1.2.0: %v", err)
	}
	goMod, err := deps.gerrit.ReadFile(ctx, "foo", tag.Revision, "go.mod")
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(string(goMod), "mod@v1.1.0") {
		t.Errorf("foo should use mod v1.1.0. go.mod: %v", string(goMod))
	}
}

type verboseListener struct {
	t              *testing.T
	outputListener func(string, interface{})
}

func (l *verboseListener) WorkflowStalled(workflowID uuid.UUID) error {
	l.t.Logf("workflow %q: stalled", workflowID.String())
	return nil
}

func (l *verboseListener) TaskStateChanged(_ uuid.UUID, _ string, st *workflow.TaskState) error {
	switch {
	case !st.Finished:
		l.t.Logf("task %-10v: started", st.Name)
	case st.Error != "":
		l.t.Logf("task %-10v: error: %v", st.Name, st.Error)
	default:
		l.t.Logf("task %-10v: done: %v", st.Name, st.Result)
		if l.outputListener != nil {
			l.outputListener(st.Name, st.Result)
		}
	}
	return nil
}

func (l *verboseListener) Logger(_ uuid.UUID, task string) workflow.Logger {
	return &testLogger{t: l.t, task: task}
}

type testLogger struct {
	t    *testing.T
	task string // Optional.
}

func (l *testLogger) Printf(format string, v ...interface{}) {
	l.t.Logf("%v\ttask %-10v: LOG: %s", time.Now(), l.task, fmt.Sprintf(format, v...))
}

type fakeDashboard func(string) *types.BuildStatus

func (d fakeDashboard) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	resp := d(r.URL.Query().Get("repo"))
	if resp == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}
	json.NewEncoder(w).Encode(resp)
}
