package repo_manager

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"testing"

	github_api "github.com/google/go-github/v29/github"
	"github.com/stretchr/testify/require"
	"go.skia.org/infra/autoroll/go/codereview"
	"go.skia.org/infra/autoroll/go/config"
	"go.skia.org/infra/autoroll/go/repo_manager/parent"
	"go.skia.org/infra/autoroll/go/revision"
	"go.skia.org/infra/go/exec"
	"go.skia.org/infra/go/git"
	git_testutils "go.skia.org/infra/go/git/testutils"
	"go.skia.org/infra/go/github"
	"go.skia.org/infra/go/mockhttpclient"
	"go.skia.org/infra/go/recipe_cfg"
	"go.skia.org/infra/go/testutils"
)

const (
	githubVersionFile = "version-file.txt"
)

func githubCR(t *testing.T, g *github.GitHub) codereview.CodeReview {
	rv, err := codereview.NewGitHub(&config.GitHubConfig{
		RepoOwner:     "me",
		RepoName:      "my-repo",
		ChecksWaitFor: []string{"a", "b", "c"},
	}, g)
	require.NoError(t, err)
	return rv
}

func githubRmCfg(t *testing.T) *config.ParentChildRepoManagerConfig {
	return &config.ParentChildRepoManagerConfig{
		Parent: &config.ParentChildRepoManagerConfig_GitCheckoutGithubFileParent{
			GitCheckoutGithubFileParent: &config.GitCheckoutGitHubFileParentConfig{
				GitCheckout: &config.GitCheckoutGitHubParentConfig{
					GitCheckout: &config.GitCheckoutParentConfig{
						GitCheckout: &config.GitCheckoutConfig{
							Branch:  git.MainBranch,
							RepoUrl: "todo.git",
						},
						Dep: &config.DependencyConfig{
							Primary: &config.VersionFileConfig{
								Id:   "todo.git",
								Path: githubVersionFile,
							},
						},
					},
					ForkRepoUrl: "todo.git",
				},
			},
		},
		Child: &config.ParentChildRepoManagerConfig_GitCheckoutGithubChild{
			GitCheckoutGithubChild: &config.GitCheckoutGitHubChildConfig{
				GitCheckout: &config.GitCheckoutChildConfig{
					GitCheckout: &config.GitCheckoutConfig{
						Branch:  git.MainBranch,
						RepoUrl: "todo.git",
					},
				},
				RepoOwner: mockGithubUser,
				RepoName:  "todo.git",
			},
		},
	}
}

func setupGithub(t *testing.T, cfg *config.ParentChildRepoManagerConfig) (context.Context, *parentChildRepoManager, string, *git_testutils.GitBuilder, []string, *git_testutils.GitBuilder, *exec.CommandCollector, *mockhttpclient.URLMock, func()) {
	wd, err := ioutil.TempDir("", "")
	require.NoError(t, err)
	ctx := context.Background()

	// Create child and parent repos.
	childPath := filepath.Join(wd, "earth")
	require.NoError(t, os.MkdirAll(childPath, 0755))
	child := git_testutils.GitInitWithDir(t, ctx, childPath, git.MainBranch)
	f := "somefile.txt"
	childCommits := make([]string, 0, 10)
	for i := 0; i < numChildCommits; i++ {
		childCommits = append(childCommits, child.CommitGen(ctx, f))
	}

	parentPath := filepath.Join(wd, "krypton")
	require.NoError(t, os.MkdirAll(parentPath, 0755))
	parent := git_testutils.GitInitWithDir(t, ctx, parentPath, git.MainBranch)
	parent.Add(ctx, githubVersionFile, fmt.Sprintf(`%s`, childCommits[0]))
	parent.Commit(ctx)

	fork := git_testutils.GitInit(t, ctx)
	fork.Git(ctx, "remote", "set-url", git.DefaultRemote, parent.RepoUrl())
	fork.Git(ctx, "fetch", git.DefaultRemote)
	fork.Git(ctx, "checkout", git.MainBranch)
	fork.Git(ctx, "reset", "--hard", git.DefaultRemoteBranch)

	parentCfg := cfg.Parent.(*config.ParentChildRepoManagerConfig_GitCheckoutGithubFileParent).GitCheckoutGithubFileParent
	parentCfg.GitCheckout.ForkRepoUrl = fork.RepoUrl()
	parentCfg.GitCheckout.GitCheckout.GitCheckout.RepoUrl = parent.RepoUrl()
	parentCfg.GitCheckout.GitCheckout.Dep.Primary.Id = child.RepoUrl()
	childCfg := cfg.Child.(*config.ParentChildRepoManagerConfig_GitCheckoutGithubChild).GitCheckoutGithubChild
	childCfg.GitCheckout.GitCheckout.RepoUrl = child.RepoUrl()
	childCfg.RepoName = child.RepoUrl()

	mockRun := &exec.CommandCollector{}
	mockRun.SetDelegateRun(func(ctx context.Context, cmd *exec.Command) error {
		if strings.Contains(cmd.Name, "git") {
			if cmd.Args[0] == "clone" || cmd.Args[0] == "fetch" {
				return nil
			}
			if cmd.Args[0] == "checkout" && cmd.Args[1] == "remote/"+git.MainBranch {
				// Pretend origin is the remote branch for testing ease.
				cmd.Args[1] = git.DefaultRemoteBranch
			}
		}
		return exec.DefaultRun(ctx, cmd)
	})
	ctx = exec.NewContext(ctx, mockRun.Run)

	recipesCfg := filepath.Join(testutils.GetRepoRoot(t), recipe_cfg.RECIPE_CFG_PATH)

	g, urlMock := setupFakeGithub(ctx, t, childCommits)
	rm, err := newParentChildRepoManager(ctx, cfg, setupRegistry(t), wd, "rollerName", recipesCfg, "fake.server.com", urlMock.Client(), githubCR(t, g))
	require.NoError(t, err)

	cleanup := func() {
		testutils.RemoveAll(t, wd)
		child.Cleanup()
		parent.Cleanup()
	}

	return ctx, rm, wd, child, childCommits, parent, mockRun, urlMock, cleanup
}

func setupFakeGithub(ctx context.Context, t *testing.T, childCommits []string) (*github.GitHub, *mockhttpclient.URLMock) {
	urlMock := mockhttpclient.NewURLMock()

	// Mock /user endpoint.
	serializedUser, err := json.Marshal(&github_api.User{
		Login: &mockGithubUser,
		Email: &mockGithubUserEmail,
	})
	require.NoError(t, err)
	urlMock.MockOnce(githubApiUrl+"/user", mockhttpclient.MockGetDialogue(serializedUser))

	if childCommits != nil && len(childCommits) > 0 {
		// Mock getRawFile.
		urlMock.MockOnce("https://raw.githubusercontent.com/superman/krypton/master/fake-file.txt", mockhttpclient.MockGetDialogue([]byte(childCommits[0])))
	}

	// Mock /issues endpoint for get and patch requests.
	serializedIssue, err := json.Marshal(&github_api.Issue{
		Labels: []github_api.Label{},
	})
	require.NoError(t, err)
	urlMock.MockOnce(githubApiUrl+"/repos/superman/krypton/issues/12345", mockhttpclient.MockGetDialogue(serializedIssue))
	patchRespBody := []byte(testutils.MarshalJSON(t, &github_api.PullRequest{}))
	patchReqType := "application/json"
	patchReqBody := []byte(`{"labels":["autosubmit"]}
`)
	patchMd := mockhttpclient.MockPatchDialogue(patchReqType, patchReqBody, patchRespBody)
	urlMock.MockOnce(githubApiUrl+"/repos/superman/krypton/issues/12345", patchMd)

	g, err := github.NewGitHub(ctx, "superman", "krypton", urlMock.Client())
	require.NoError(t, err)
	return g, urlMock
}

func mockGithubRequests(t *testing.T, urlMock *mockhttpclient.URLMock, forkRepoURL string) {
	// Mock /pulls endpoint.
	serializedPull, err := json.Marshal(&github_api.PullRequest{
		Number: &testPullNumber,
	})
	require.NoError(t, err)
	reqType := "application/json"
	md := mockhttpclient.MockPostDialogueWithResponseCode(reqType, mockhttpclient.DONT_CARE_REQUEST, serializedPull, http.StatusCreated)
	urlMock.MockOnce(githubApiUrl+"/repos/superman/krypton/pulls", md)

	// Mock /comments endpoint.
	reqType = "application/json"
	reqBody := []byte(`{"body":"@reviewer : New roll has been created by fake.server.com"}
`)
	md = mockhttpclient.MockPostDialogueWithResponseCode(reqType, reqBody, nil, http.StatusCreated)
	urlMock.MockOnce(githubApiUrl+"/repos/superman/krypton/issues/12345/comments", md)

	// Mock /refs endpoints.
	forkRepoMatches := parent.REGitHubForkRepoURL.FindStringSubmatch(forkRepoURL)
	forkRepoOwner := forkRepoMatches[2]
	forkRepoName := forkRepoMatches[3]
	testSHA := "xyz"
	serializedRef, err := json.Marshal(&github_api.Reference{
		Object: &github_api.GitObject{
			SHA: &testSHA,
		},
	})
	require.NoError(t, err)
	urlMock.MockOnce(fmt.Sprintf("%s/repos/%s/%s/git/refs/%s", githubApiUrl, forkRepoOwner, forkRepoName, "heads%2F"+git.MainBranch), mockhttpclient.MockGetDialogue(serializedRef))
	md = mockhttpclient.MockPostDialogueWithResponseCode(reqType, mockhttpclient.DONT_CARE_REQUEST, nil, http.StatusCreated)
	urlMock.MockOnce(fmt.Sprintf("%s/repos/%s/%s/git/refs", githubApiUrl, forkRepoOwner, forkRepoName), md)
	require.NoError(t, err)
}

// TestGithubRepoManager tests all aspects of the Github RepoManager except for CreateNewRoll.
func TestGithubRepoManager(t *testing.T) {

	cfg := githubRmCfg(t)
	ctx, rm, _, _, childCommits, _, _, _, cleanup := setupGithub(t, cfg)
	defer cleanup()

	lastRollRev, tipRev, notRolledRevs, err := rm.Update(ctx)
	require.NoError(t, err)
	require.Equal(t, childCommits[0], lastRollRev.Id)
	require.Equal(t, childCommits[len(childCommits)-1], tipRev.Id)
	require.Equal(t, len(childCommits)-1, len(notRolledRevs))
}

func TestGithubRepoManagerCreateNewRoll(t *testing.T) {

	cfg := githubRmCfg(t)
	ctx, rm, _, _, _, _, _, urlMock, cleanup := setupGithub(t, cfg)
	defer cleanup()

	lastRollRev, tipRev, notRolledRevs, err := rm.Update(ctx)
	require.NoError(t, err)

	// Create a roll.
	mockGithubRequests(t, urlMock, cfg.GetGitCheckoutGithubFileParent().GitCheckout.ForkRepoUrl)
	issue, err := rm.CreateNewRoll(ctx, lastRollRev, tipRev, notRolledRevs, emails, false, fakeCommitMsg)
	require.NoError(t, err)
	require.Equal(t, issueNum, issue)
}

// Verify that we ran the PreUploadSteps.
func TestGithubRepoManagerPreUploadSteps(t *testing.T) {

	cfg := githubRmCfg(t)
	// Create a fake pre-upload step.
	ran := false
	stepName := parent.AddPreUploadStepForTesting(func(context.Context, []string, *http.Client, string, *revision.Revision, *revision.Revision) error {
		ran = true
		return nil
	})
	parentCfg := cfg.Parent.(*config.ParentChildRepoManagerConfig_GitCheckoutGithubFileParent).GitCheckoutGithubFileParent
	parentCfg.PreUploadSteps = []config.PreUploadStep{stepName}
	ctx, rm, _, _, _, _, _, urlMock, cleanup := setupGithub(t, cfg)
	defer cleanup()

	lastRollRev, tipRev, notRolledRevs, err := rm.Update(ctx)
	require.NoError(t, err)

	// Create a roll, assert that we ran the PreUploadSteps.
	mockGithubRequests(t, urlMock, parentCfg.GitCheckout.ForkRepoUrl)
	_, createErr := rm.CreateNewRoll(ctx, lastRollRev, tipRev, notRolledRevs, emails, false, fakeCommitMsg)
	require.NoError(t, createErr)
	require.True(t, ran)
}

// Verify that we fail when a PreUploadStep fails.
func TestGithubRepoManagerPreUploadStepsError(t *testing.T) {

	cfg := githubRmCfg(t)
	// Create a fake pre-upload step.
	ran := false
	expectedErr := errors.New("Expected error")
	stepName := parent.AddPreUploadStepForTesting(func(context.Context, []string, *http.Client, string, *revision.Revision, *revision.Revision) error {
		ran = true
		return expectedErr
	})
	parentCfg := cfg.Parent.(*config.ParentChildRepoManagerConfig_GitCheckoutGithubFileParent).GitCheckoutGithubFileParent
	parentCfg.PreUploadSteps = []config.PreUploadStep{stepName}

	ctx, rm, _, _, _, _, _, urlMock, cleanup := setupGithub(t, cfg)
	defer cleanup()

	lastRollRev, tipRev, notRolledRevs, err := rm.Update(ctx)
	require.NoError(t, err)

	// Create a roll, assert that we ran the PreUploadSteps.
	mockGithubRequests(t, urlMock, parentCfg.GitCheckout.ForkRepoUrl)
	_, createErr := rm.CreateNewRoll(ctx, lastRollRev, tipRev, notRolledRevs, emails, false, fakeCommitMsg)
	require.Error(t, expectedErr, createErr)
	require.True(t, ran)
}
