package gitiles

import (
	"context"
	"fmt"
	"sort"
	"strings"
	"testing"
	"time"

	assert "github.com/stretchr/testify/require"
	"go.skia.org/infra/go/deepequal"
	"go.skia.org/infra/go/git"
	git_testutils "go.skia.org/infra/go/git/testutils"
	"go.skia.org/infra/go/mockhttpclient"
	"go.skia.org/infra/go/testutils"
	"go.skia.org/infra/go/vcsinfo"
)

func TestLog(t *testing.T) {
	testutils.MediumTest(t)

	// Setup. The test repo looks like this:
	/*
		$ git log --graph --date-order
		* commit c8
		|
		*   commit c7
		|\  Merge: c5 c6
		| |
		| * commit c6
		| |
		* | commit c5
		| |
		* | commit c4
		| |
		| * commit c3
		| |
		| * commit c2
		|/
		|
		* commit c1
		|
		* commit c0
	*/
	ctx := context.Background()
	gb := git_testutils.GitInit(t, ctx)
	now := time.Now()
	c0 := gb.CommitGenAt(ctx, "file1", now)
	now = now.Add(time.Second)
	c1 := gb.CommitGenAt(ctx, "file1", now)
	now = now.Add(time.Second)
	gb.CreateBranchTrackBranch(ctx, "branch2", "master")
	c2 := gb.CommitGenAt(ctx, "file2", now)
	now = now.Add(time.Second)
	c3 := gb.CommitGenAt(ctx, "file2", now)
	now = now.Add(time.Second)
	gb.CheckoutBranch(ctx, "master")
	c4 := gb.CommitGenAt(ctx, "file1", now)
	now = now.Add(time.Second)
	c5 := gb.CommitGenAt(ctx, "file1", now)
	now = now.Add(time.Second)
	gb.CheckoutBranch(ctx, "branch2")
	c6 := gb.CommitGenAt(ctx, "file2", now)
	now = now.Add(time.Second)
	gb.CheckoutBranch(ctx, "master")
	c7 := gb.MergeBranch(ctx, "branch2")
	now = now.Add(time.Second)
	c8 := gb.CommitGenAt(ctx, "file1", now)

	// Use all of the commit variables so the compiler doesn't complain.
	repo := git.GitDir(gb.Dir())
	commits := []string{c8, c7, c6, c5, c4, c3, c2, c1, c0}
	details := make(map[string]*vcsinfo.LongCommit, len(commits))
	for _, c := range commits {
		d, err := repo.Details(ctx, c)
		assert.NoError(t, err)
		details[c] = d
	}

	urlMock := mockhttpclient.NewURLMock()
	r := NewRepo(gb.RepoUrl(), "", urlMock.Client())

	// Helper function for mocking gitiles API calls.
	mockLog := func(from, to string, rvCommits []string) {
		// Create the mock results.
		results := &Log{
			Log: make([]*Commit, 0, len(rvCommits)),
		}
		for _, c := range rvCommits {
			d := details[c]
			results.Log = append(results.Log, &Commit{
				Commit:  d.Hash,
				Parents: d.Parents,
				Author: &Author{
					Name:  "don't care",
					Email: "don't care",
					Time:  d.Timestamp.Format(DATE_FORMAT_NO_TZ),
				},
				Committer: &Author{
					Name:  "don't care",
					Email: "don't care",
					Time:  d.Timestamp.Format(DATE_FORMAT_NO_TZ),
				},
				Message: d.Subject,
			})
		}
		js := testutils.MarshalJSON(t, results)
		js = ")]}'\n" + js
		urlMock.MockOnce(fmt.Sprintf(LOG_URL, gb.RepoUrl(), from, to), mockhttpclient.MockGetDialogue([]byte(js)))
	}

	// Return a slice of the hashes for the given commits.
	hashes := func(commits []*vcsinfo.LongCommit) []string {
		rv := make([]string, 0, len(commits))
		for _, c := range commits {
			rv = append(rv, c.Hash)
		}
		return rv
	}

	// Verify that we got the correct list of commits from the call to Log.
	checkGitiles := func(fn func(string, string) ([]*vcsinfo.LongCommit, error), from, to string, expect []string) {
		mockLog(from, to, expect)
		log, err := fn(from, to)
		assert.NoError(t, err)
		deepequal.AssertDeepEqual(t, hashes(log), expect)
		assert.True(t, urlMock.Empty())
	}

	// Verify that we get the correct list of commits from Git. This is so
	// that we can ensure that our test expectations of the library are
	// consistent with the actual behavior of Git.
	checkGit := func(from, to string, expect []string, args ...string) {
		cmd := []string{"rev-list", "--date-order"}
		cmd = append(cmd, args...)
		cmd = append(cmd, fmt.Sprintf("%s..%s", from, to))
		output, err := repo.Git(ctx, cmd...)
		assert.NoError(t, err)
		log := strings.Split(strings.TrimSpace(output), "\n")
		// Empty response results in a single-item list with one empty
		// string...
		if len(log) == 1 && log[0] == "" {
			log = log[1:]
		}
		deepequal.AssertDeepEqual(t, log, expect)
	}

	// Verify that we get the expected list of commits from both Gitiles
	// (Repo.Log) and Git ("git log --date-order").
	checkBasic := func(from, to string, expect []string) {
		checkGit(from, to, expect)
		checkGitiles(r.Log, from, to, expect)
	}

	// Verify that we get the expected list of commits from both Gitiles
	// (Repo.LogLinear) and Git
	// ("git log --date-order --first-parent --ancestry-path).
	checkLinear := func(from, to string, expect []string) {
		checkGit(from, to, expect, "--first-parent", "--ancestry-path")
		checkGitiles(r.LogLinear, from, to, expect)
	}

	// Test cases.
	checkBasic(c0, c8, []string{c8, c7, c6, c5, c4, c3, c2, c1})
	checkLinear(c0, c8, []string{c8, c7, c5, c4, c1})
	checkBasic(c0, c1, []string{c1})
	checkLinear(c0, c1, []string{c1})
	checkBasic(c2, c4, []string{c4})
	checkLinear(c2, c4, []string{})
	checkBasic(c1, c2, []string{c2})
	checkLinear(c1, c2, []string{c2})
	checkBasic(c1, c4, []string{c4})
	checkLinear(c1, c4, []string{c4})
	checkBasic(c5, c7, []string{c7, c6, c3, c2})
	checkLinear(c5, c7, []string{c7})
	checkBasic(c2, c7, []string{c7, c6, c5, c4, c3})
	checkLinear(c2, c7, []string{})
}

func TestLogPagination(t *testing.T) {
	testutils.MediumTest(t)

	// Gitiles API paginates logs over 100 commits long.
	repoUrl := "https://fake/repo"
	urlMock := mockhttpclient.NewURLMock()
	repo := NewRepo(repoUrl, "", urlMock.Client())
	next := 0
	hash := func() string {
		next++
		return fmt.Sprintf("%040d", next)
	}
	ts := time.Now().Truncate(time.Second).UTC()
	var last *vcsinfo.LongCommit
	commit := func() *vcsinfo.LongCommit {
		ts = ts.Add(time.Second)
		rv := &vcsinfo.LongCommit{
			ShortCommit: &vcsinfo.ShortCommit{
				Hash:    hash(),
				Author:  "don't care (don't care)",
				Subject: "don't care",
			},
			Timestamp: ts,
		}
		if last != nil {
			rv.Parents = []string{last.Hash}
		}
		last = rv
		return rv
	}
	mock := func(from, to *vcsinfo.LongCommit, commits []*vcsinfo.LongCommit, next string) {
		// Create the mock results.
		results := &Log{
			Log:  make([]*Commit, 0, len(commits)),
			Next: next,
		}
		for i := len(commits) - 1; i >= 0; i-- {
			c := commits[i]
			results.Log = append(results.Log, &Commit{
				Commit:  c.Hash,
				Parents: c.Parents,
				Author: &Author{
					Name:  "don't care",
					Email: "don't care",
					Time:  c.Timestamp.Format(DATE_FORMAT_NO_TZ),
				},
				Committer: &Author{
					Name:  "don't care",
					Email: "don't care",
					Time:  c.Timestamp.Format(DATE_FORMAT_NO_TZ),
				},
				Message: "don't care",
			})
		}
		js := testutils.MarshalJSON(t, results)
		js = ")]}'\n" + js
		urlMock.MockOnce(fmt.Sprintf(LOG_URL, repoUrl, from.Hash, to.Hash), mockhttpclient.MockGetDialogue([]byte(js)))
	}
	check := func(from, to *vcsinfo.LongCommit, expect []*vcsinfo.LongCommit) {
		log, err := repo.Log(from.Hash, to.Hash)
		assert.NoError(t, err)
		sort.Sort(sort.Reverse(vcsinfo.LongCommitSlice(log)))
		deepequal.AssertDeepEqual(t, expect, log)
	}

	// Create some fake commits.
	commits := []*vcsinfo.LongCommit{}
	for i := 0; i < 10; i++ {
		commits = append(commits, commit())
	}

	// Most basic test case; no pagination.
	mock(commits[0], commits[5], commits[0:5], "")
	check(commits[0], commits[5], commits[0:5])

	// Two pages.
	split := 5
	mock(commits[0], commits[len(commits)-1], commits[split:], commits[split].Hash)
	mock(commits[0], commits[split], commits[0:split], "")
	check(commits[0], commits[len(commits)-1], commits)

	// Three pages.
	split1 := 7
	split2 := 3
	mock(commits[0], commits[len(commits)-1], commits[split1:], commits[split1].Hash)
	mock(commits[0], commits[split1], commits[split2:split1], commits[split2].Hash)
	mock(commits[0], commits[split2], commits[0:split2], "")
	check(commits[0], commits[len(commits)-1], commits)
}
