// 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(context.Background(), 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)
			}
		})
	}
}
