// Copyright 2020 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This package contains the error interface returned by changelog and
// findbuild packages. It includes functions to retrieve HTTP status codes
// from Gerrit and Gitiles errors, and functions to create ChangelogErrors
// relevant to the changelog and findbuild features.

package utils

import (
	"context"
	"fmt"
	"net/http"
	"strings"
	"testing"

	"github.com/beevik/etree"
	"go.chromium.org/luci/common/api/gerrit"
	"go.chromium.org/luci/common/api/gitiles"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

const (
	cosGoBURL    = "cos.googlesource.com"
	manifestRepo = "cos/manifest-snapshots"
)

type repo struct {
	// The Git on Borg instance to query from.
	InstanceURL string
	// A value that points to the last commit for a build on a given repo.
	// Acceptable values:
	// - A commit SHA
	// - A ref, ex. "refs/heads/branch"
	// - A ref defined as n-th parent of R in the form "R-n".
	//   ex. "master-2" or "deadbeef-1".
	// Source: https://pkg.go.dev/go.chromium.org/luci/common/proto/gitiles?tab=doc#LogRequest
	Committish string
}

func getHTTPClient() (*http.Client, error) {
	creds, err := google.FindDefaultCredentials(context.Background(), gerrit.OAuthScope)
	if err != nil {
		return nil, fmt.Errorf("no application default credentials found - run `gcloud auth application-default login` and try again")
	}
	return oauth2.NewClient(oauth2.NoContext, creds.TokenSource), nil
}

// repoMap generates a mapping of repo name to instance URL and committish.
// This eliminates the need to track remote names and allows lookup
// of source committish when generating changelog.
func repoMap(manifest string) (map[string]*repo, error) {
	if manifest == "" {
		return nil, fmt.Errorf("repoMap: manifest data is empty")
	}
	doc := etree.NewDocument()
	if err := doc.ReadFromString(manifest); err != nil {
		return nil, fmt.Errorf("repoMap: error parsing manifest xml:\n%v", err)
	}
	root := doc.SelectElement("manifest")

	// Parse each <remote fetch=X name=Y> tag in the manifest xml file.
	// Extract the "fetch" and "name" attributes from each remote tag, and map the name to the fetch URL.
	remoteMap := make(map[string]string)
	for _, remote := range root.SelectElements("remote") {
		url := strings.Replace(remote.SelectAttr("fetch").Value, "https://", "", 1)
		remoteMap[remote.SelectAttr("name").Value] = url
	}

	// Parse each <project name=X remote=Y revision=Z> tag in the manifest xml file.
	// Extract the "name", "remote", and "revision" attributes from each project tag.
	// Some projects do not have a "remote" attribute.
	// If this is the case, they should use the default remoteURL.
	if root.SelectElement("default").SelectAttr("remote") != nil {
		remoteMap[""] = remoteMap[root.SelectElement("default").SelectAttr("remote").Value]
	}
	repos := make(map[string]*repo)
	for _, project := range root.SelectElements("project") {
		repos[project.SelectAttr("name").Value] = &repo{
			InstanceURL: remoteMap[project.SelectAttrValue("remote", "")],
			Committish:  project.SelectAttr("revision").Value,
		}
	}
	return repos, nil
}

func TestDownloadManifest(t *testing.T) {
	tests := map[string]struct {
		ManifestRepo string
		BuildNum     string
		ShouldError  bool
	}{
		"master branch": {
			ManifestRepo: manifestRepo,
			BuildNum:     "15000.0.0",
			ShouldError:  false,
		},
		"release branch": {
			ManifestRepo: manifestRepo,
			BuildNum:     "13310.1035.0",
			ShouldError:  false,
		},
		"invalid build": {
			ManifestRepo: manifestRepo,
			BuildNum:     "1.1551226.0",
			ShouldError:  true,
		},
		"invalid manifest repo": {
			ManifestRepo: manifestRepo,
			BuildNum:     "1.1551226.0",
			ShouldError:  true,
		},
	}
	httpClient, _ := getHTTPClient()
	gobClient, _ := gitiles.NewRESTClient(httpClient, cosGoBURL, false)
	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			resp, err := DownloadManifest(gobClient, test.ManifestRepo, test.BuildNum)
			if (err != nil) != test.ShouldError {
				ShouldError := "no error"
				if test.ShouldError {
					ShouldError = "some error"
				}
				t.Fatalf("expected %s, got: %v", ShouldError, err)
			}
			if !test.ShouldError {
				_, err = repoMap(resp.Contents)
				if err != nil {
					t.Fatalf("expected parsable manifest file, got %v while attempting to parse response", err)
				}
			}
		})
	}
}

func TestCommits(t *testing.T) {
	tests := map[string]struct {
		Repo        string
		SHA         string
		AncestorSHA string
		QuerySize   int
		ShouldError bool
		MoreCommits bool
	}{
		"no ancestor": {
			Repo:      "cos/cobble",
			SHA:       "a910c096139769e35720174069e81e89bf90fdc6",
			QuerySize: -1,
		},
		"ancestor specified": {
			Repo:        "cos/cobble",
			SHA:         "a910c096139769e35720174069e81e89bf90fdc6",
			AncestorSHA: "30a49d0373138996adcd90f80a5adfba9a342c6d",
			QuerySize:   -1,
		},
		"query size": {
			Repo:        "third_party/kernel",
			SHA:         "f8649a7408c63f53937e33b0e8379679b0434849",
			QuerySize:   15000,
			MoreCommits: true,
		},
		"incorrect repo": {
			Repo:        "not/arepo",
			SHA:         "a910c096139769e35720174069e81e89bf90fdc6",
			QuerySize:   -1,
			ShouldError: true,
		},
		"nonexistant-SHA": {
			Repo:        manifestRepo,
			SHA:         "a910c096139769e35720174069e81e89bddddddd",
			ShouldError: true,
		},
	}
	httpClient, _ := getHTTPClient()
	gobClient, _ := gitiles.NewRESTClient(httpClient, cosGoBURL, false)
	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			commits, moreCommits, err := Commits(gobClient, test.Repo, test.SHA, test.AncestorSHA, test.QuerySize)
			if (err != nil) != test.ShouldError {
				ShouldError := "no error"
				if test.ShouldError {
					ShouldError = "some error"
				}
				t.Fatalf("expected %s, got: %v", ShouldError, err)
			}
			if !test.ShouldError {
				switch {
				case len(commits) == 0:
					t.Fatalf("expected non-empty commits list, got empty list")
				case test.QuerySize != -1 && len(commits) > test.QuerySize:
					t.Fatalf("expected commits list of at most %d commits, got commits list with %d commits", test.QuerySize, len(commits))
				case moreCommits != test.MoreCommits:
					t.Fatalf("expected moreCommits = %v, got moreCommits = %v", test.MoreCommits, moreCommits)
				case commits[0].Id != test.SHA:
					t.Fatalf("expected commits list to start with commit %s, got %s as starting commit", test.SHA, commits[0].Id)
				}
			}
		})
	}
}

func TestCreateGerritURL(t *testing.T) {
	tests := map[string]struct {
		input   string
		output  string
		wantErr bool
	}{
		"SuccessHTTP": {
			input:  "https://cos.googlesource.com",
			output: "https://cos-review.googlesource.com",
		},
		"SuccessWithoutHTTP": {
			input:  "cos.googlesource.com",
			output: "https://cos-review.googlesource.com",
		},
		"Failure": {
			input:   "https://cos.googleSource.com",
			wantErr: true,
		},
	}
	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			gotOutput, err := CreateGerritURL(test.input)
			if gotErr := err != nil; gotErr != test.wantErr {
				t.Fatalf("CreateGerritURL(%s) = %v", test.input, err)
			}
			if !test.wantErr && gotOutput != test.output {
				t.Fatalf("CreateGerritURL(%s), got %s, want %s", test.input, gotOutput, test.output)
			}
		})
	}
}
