// 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.

package controllers

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"strings"
	"text/template"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	"cos.googlesource.com/cos/tools.git/src/pkg/changelog"
	"cos.googlesource.com/cos/tools.git/src/pkg/findbuild"
	"cos.googlesource.com/cos/tools.git/src/pkg/utils"

	log "github.com/sirupsen/logrus"
)

const (
	subjectLen int = 100
)

var (
	internalGerritInstance         string
	internalFallbackGerritInstance string
	internalGoBInstance            string
	internalManifestRepo           string
	croslandURL                    string
	externalGerritInstance         string
	externalFallbackGerritInstance string
	externalGoBInstance            string
	externalManifestRepo           string
	envQuerySize                   string
	envBoard                       string
	artifactsBucket                string

	staticBasePath            string
	indexTemplate             *template.Template
	readme                    *template.Template
	changelogTemplate         *template.Template
	promptLoginTemplate       *template.Template
	findBuildTemplate         *template.Template
	findReleasedBuildTemplate *template.Template
	statusForbiddenTemplate   *template.Template
	basicTextTemplate         *template.Template
)

func init() {
	var err error
	client, err := secretmanager.NewClient(context.Background())
	if err != nil {
		log.Fatalf("Failed to setup client: %v", err)
	}
	internalGerritInstance, err = getSecret(client, os.Getenv("COS_INTERNAL_GERRIT_INSTANCE_NAME"))
	if err != nil {
		log.Fatalf("Failed to retrieve secret for COS_INTERNAL_GERRIT_INSTANCE_NAME with key name %s\n%v", os.Getenv("COS_INTERNAL_GERRIT_INSTANCE_NAME"), err)
	}
	internalFallbackGerritInstance, err = getSecret(client, os.Getenv("COS_INTERNAL_FALLBACK_GERRIT_INSTANCE_NAME"))
	if err != nil {
		log.Fatalf("Failed to retrieve secret for COS_INTERNAL_FALLBACK_GERRIT_INSTANCE_NAME with key name %s\n%v", os.Getenv("COS_INTERNAL_FALLBACK_GERRIT_INSTANCE_NAME"), err)
	}
	internalGoBInstance, err = getSecret(client, os.Getenv("COS_INTERNAL_GOB_INSTANCE_NAME"))
	if err != nil {
		log.Fatalf("Failed to retrieve secret for COS_INTERNAL_GOB_INSTANCE_NAME with key name %s\n%v", os.Getenv("COS_INTERNAL_GOB_INSTANCE_NAME"), err)
	}
	internalManifestRepo, err = getSecret(client, os.Getenv("COS_INTERNAL_MANIFEST_REPO_NAME"))
	if err != nil {
		log.Fatalf("Failed to retrieve secret for COS_INTERNAL_MANIFEST_REPO_NAME with key name %s\n%v", os.Getenv("COS_INTERNAL_MANIFEST_REPO_NAME"), err)
	}
	croslandURL, err = getSecret(client, os.Getenv("CROSLAND_NAME"))
	if err != nil {
		log.Fatalf("Failed to retrieve secret for CROSLAND_NAME with key name %s\n%v", os.Getenv("CROSLAND_NAME"), err)
	}
	artifactsBucket, err = getSecret(client, os.Getenv("COS_CHANGELOG_ARTIFACTS_BUCKET_NAME"))
	if err != nil {
		log.Fatalf("Failed to retrieve secret for COS_CHANGELOG_ARTIFACTS_BUCKET_NAME with key name %s\n%v", os.Getenv("COS_CHANGELOG_ARTIFACTS_BUCKET_NAME"), err)
	}

	externalGerritInstance = os.Getenv("COS_EXTERNAL_GERRIT_INSTANCE")
	externalFallbackGerritInstance = os.Getenv("COS_EXTERNAL_FALLBACK_GERRIT_INSTANCE")
	externalGoBInstance = os.Getenv("COS_EXTERNAL_GOB_INSTANCE")
	externalManifestRepo = os.Getenv("COS_EXTERNAL_MANIFEST_REPO")
	envBoard = os.Getenv("BOARD_NAME")
	envQuerySize = getIntVerifiedEnv("CHANGELOG_QUERY_SIZE")
	staticBasePath = os.Getenv("STATIC_BASE_PATH")
	indexTemplate = template.Must(template.ParseFiles(staticBasePath + "templates/index.html"))
	readme = template.Must(template.ParseFiles(staticBasePath + "templates/readme.html"))
	changelogTemplate = template.Must(template.ParseFiles(staticBasePath + "templates/changelog.html"))
	findBuildTemplate = template.Must(template.ParseFiles(staticBasePath + "templates/findBuild.html"))
	findReleasedBuildTemplate = template.Must(template.ParseFiles(staticBasePath + "templates/findReleasedBuild.html"))
	promptLoginTemplate = template.Must(template.ParseFiles(staticBasePath + "templates/promptLogin.html"))
	basicTextTemplate = template.Must(template.ParseFiles(staticBasePath + "templates/error.html"))
}

type changelogData struct {
	Source    string
	Target    string
	Additions map[string]*changelog.RepoLog
	Removals  map[string]*changelog.RepoLog
	Internal  bool
}

type changelogPage struct {
	Source          string
	Target          string
	SourceBoard     string
	SourceMilestone string
	TargetBoard     string
	TargetMilestone string
	QuerySize       string
	RepoTables      []*repoTable
	Internal        bool
	Sysctl          sysctlChanges
}

type sysctlChanges struct {
	Changes  [][]string
	NotFound string
	NotEmpty bool
}

type findBuildPage struct {
	CL         string
	CLNum      string
	BuildNum   string
	GerritLink string
	Internal   bool
}

type statusPage struct {
	ActivePage string
	SignedIn   bool
}

type basicTextPage struct {
	Header     string
	Body       string
	ActivePage string
	SignedIn   bool
}

type repoTable struct {
	Name          string
	Additions     []*repoTableEntry
	Removals      []*repoTableEntry
	AdditionsLink string
	RemovalsLink  string
}

type repoTableEntry struct {
	IsAddition    bool
	SHA           *shaAttr
	Subject       string
	Bugs          []*bugAttr
	AuthorName    string
	CommitterName string
	CommitTime    string
	ReleaseNote   string
}

type shaAttr struct {
	Name string
	URL  string
}

type bugAttr struct {
	Name string
	URL  string
}

// getIntVerifiedEnv retrieves an environment variable but checks that it can be
// converted to int first
func getIntVerifiedEnv(envName string) string {
	output := os.Getenv(envName)
	if _, err := strconv.Atoi(output); err != nil {
		log.Errorf("failed to parse env variable %s with value %s: %v",
			envName, os.Getenv(output), err)
	}
	return output
}

func gobCommitLink(instance, repo, SHA string) string {
	return fmt.Sprintf("https://%s/%s/+/%s", instance, repo, SHA)
}

func gobDiffLink(instance, repo, sourceSHA, targetSHA string, diffLink bool) string {
	if !diffLink {
		return fmt.Sprintf("https://%s/%s/+log/%s?n=10000", instance, repo, targetSHA)
	}
	return fmt.Sprintf("https://%s/%s/+log/%s..%s?n=10000", instance, repo, sourceSHA, targetSHA)
}

func createRepoTableEntry(instance, repo string, commit *changelog.Commit, isAddition bool) *repoTableEntry {
	entry := new(repoTableEntry)
	entry.IsAddition = isAddition
	entry.SHA = &shaAttr{Name: commit.SHA[:8], URL: gobCommitLink(instance, repo, commit.SHA)}
	entry.Subject = commit.Subject
	if len(entry.Subject) > subjectLen {
		entry.Subject = entry.Subject[:subjectLen]
	}
	entry.Bugs = make([]*bugAttr, len(commit.Bugs))
	for i, bugURL := range commit.Bugs {
		name := bugURL[strings.Index(bugURL, "/")+1:]
		entry.Bugs[i] = &bugAttr{Name: name, URL: "http://" + bugURL}
	}
	entry.AuthorName = commit.AuthorName
	entry.CommitterName = commit.CommitterName
	entry.CommitTime = commit.CommitTime
	entry.ReleaseNote = commit.ReleaseNote
	return entry
}

func createChangelogPage(data changelogData) *changelogPage {
	page := &changelogPage{Source: data.Source, Target: data.Target, QuerySize: envQuerySize, Internal: data.Internal}
	for repoPath, addLog := range data.Additions {
		diffLink := false
		table := &repoTable{Name: repoPath}
		for _, commit := range addLog.Commits {
			tableEntry := createRepoTableEntry(addLog.InstanceURL, addLog.Repo, commit, true)
			table.Additions = append(table.Additions, tableEntry)
		}
		if rmLog, ok := data.Removals[repoPath]; ok {
			for _, commit := range data.Removals[repoPath].Commits {
				tableEntry := createRepoTableEntry(rmLog.InstanceURL, rmLog.Repo, commit, false)
				table.Removals = append(table.Removals, tableEntry)
			}
			if data.Removals[repoPath].HasMoreCommits {
				diffLink = addLog.Repo == rmLog.Repo
				table.RemovalsLink = gobDiffLink(rmLog.InstanceURL, rmLog.Repo, addLog.TargetSHA, rmLog.TargetSHA, diffLink)
			}
		}
		if addLog.HasMoreCommits {
			table.AdditionsLink = gobDiffLink(addLog.InstanceURL, addLog.Repo, addLog.SourceSHA, addLog.TargetSHA, diffLink)
		}
		page.RepoTables = append(page.RepoTables, table)
	}
	// Add remaining repos that had removals but no additions
	for repoPath, repoLog := range data.Removals {
		if _, ok := data.Additions[repoPath]; ok {
			continue
		}
		table := &repoTable{Name: repoPath}
		for _, commit := range repoLog.Commits {
			tableEntry := createRepoTableEntry(repoLog.InstanceURL, repoLog.Repo, commit, false)
			table.Removals = append(table.Removals, tableEntry)
		}
		page.RepoTables = append(page.RepoTables, table)
		if repoLog.HasMoreCommits {
			table.RemovalsLink = gobDiffLink(repoLog.InstanceURL, repoLog.Repo, repoLog.SourceSHA, repoLog.TargetSHA, false)
		}
	}
	return page
}

func findBuildWithFallback(httpClient *http.Client, gerrit, fallbackGerrit, gob, repo, cl string, internal bool) (*findbuild.BuildResponse, bool, utils.ChangelogError) {
	didFallback := false
	request := &findbuild.BuildRequest{
		HTTPClient:   httpClient,
		GerritHost:   gerrit,
		GitilesHost:  gob,
		ManifestRepo: repo,
		CL:           cl,
	}
	buildData, err := findbuild.FindBuild(request)
	if err != nil && err.HTTPCode() == "404" {
		log.Debugf("Cl %s not found in Gerrit instance, using fallback", cl)
		fallbackRequest := &findbuild.BuildRequest{
			HTTPClient:   httpClient,
			GerritHost:   fallbackGerrit,
			GitilesHost:  gob,
			ManifestRepo: repo,
			CL:           cl,
		}
		buildData, err = findbuild.FindBuild(fallbackRequest)
		didFallback = true
	}
	return buildData, didFallback, err
}

func findReleaseBuild(httpClient *http.Client, gerrit, gob, repo, cl string, internal bool) (*findbuild.BuildResponse, utils.ChangelogError) {
	request := &findbuild.BuildRequest{
		HTTPClient:   httpClient,
		GerritHost:   gerrit,
		GitilesHost:  gob,
		ManifestRepo: repo,
		CL:           cl,
	}
	buildData, err := findbuild.FindReleasedBuild(request)
	if err != nil && err.HTTPCode() == "404" {
		log.Debugf("Cl %s not found in Gerrit instance", cl)
	}
	return buildData, err
}

// handleError creates the error page for a given error
func handleError(w http.ResponseWriter, r *http.Request, displayErr utils.ChangelogError, currPage string) {
	err := basicTextTemplate.Execute(w, &basicTextPage{
		Header:     displayErr.Header(),
		Body:       displayErr.HTMLError(),
		ActivePage: currPage,
		SignedIn:   SignedIn(r),
	})
	if err != nil {
		log.Error(err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HandleIndex serves the home page
func HandleIndex(w http.ResponseWriter, r *http.Request) {
	err := indexTemplate.Execute(w, &statusPage{SignedIn: SignedIn(r)})
	if err != nil {
		log.Error(err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HandleReadme serves the about page
func HandleReadme(w http.ResponseWriter, r *http.Request) {
	err := readme.Execute(w, &statusPage{SignedIn: SignedIn(r)})
	if err != nil {
		log.Error(err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HandleChangelog serves the changelog page
func HandleChangelog(w http.ResponseWriter, r *http.Request) {
	if RequireToken(w, r, "/changelog/") {
		return
	}
	var err error
	if err := r.ParseForm(); err != nil {
		err = changelogTemplate.Execute(w, &changelogPage{QuerySize: envQuerySize})
		if err != nil {
			log.Errorf("error executing findbuild template: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
	source := r.FormValue("source")
	target := r.FormValue("target")
	sourceMilestone := r.FormValue("source-milestone")
	targetMilestone := r.FormValue("target-milestone")
	sourceBoard := r.FormValue("source-board")
	if sourceBoard == "" {
		sourceBoard = envBoard
	}
	targetBoard := r.FormValue("target-board")
	if targetBoard == "" {
		targetBoard = envBoard
	}
	// If no source/target values specified in request, display empty changelog page
	if source == "" || target == "" {
		err = changelogTemplate.Execute(w, &changelogPage{QuerySize: envQuerySize, Internal: true})
		if err != nil {
			log.Errorf("error executing findbuild template: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
	querySize, err := strconv.Atoi(r.FormValue("n"))
	if err != nil {
		querySize, _ = strconv.Atoi(envQuerySize)
	}
	internal, instance, manifestRepo := false, externalGoBInstance, externalManifestRepo
	if r.FormValue("internal") == "true" {
		internal, instance, manifestRepo = true, internalGoBInstance, internalManifestRepo
	}
	httpClient, err := HTTPClient(w, r)
	if err != nil {
		loginURL := GetLoginURL("/changelog/", false)
		http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect)
		return
	}
	added, removed, utilErr := changelog.Changelog(httpClient, source, target, instance, manifestRepo, croslandURL, querySize)
	if utilErr != nil {
		log.Errorf("error retrieving changelog between builds %s and %s on GoB instance: %s with manifest repository: %s\n%v\n",
			source, target, externalGoBInstance, externalManifestRepo, utilErr)
		handleError(w, r, utilErr, "/changelog/")
		return
	}
	page := createChangelogPage(changelogData{
		Source:    source,
		Target:    target,
		Additions: added,
		Removals:  removed,
		Internal:  internal,
	})
	page.SourceMilestone = sourceMilestone
	page.SourceBoard = sourceBoard
	page.TargetMilestone = targetMilestone
	page.TargetBoard = targetBoard

	var foundSource, foundTarget bool
	page.Sysctl.Changes, foundSource, foundTarget = changelog.GetSysctlDiff(artifactsBucket, sourceBoard,
		sourceMilestone, source, targetBoard, targetMilestone, target)
	page.Sysctl.NotEmpty = false
	if !foundSource {
		page.Sysctl.NotFound += fmt.Sprintf("sysctl file for %s-%s-%s not found.<br>", sourceBoard, sourceMilestone, source)
		page.Sysctl.NotEmpty = true
	}
	if !foundTarget {
		page.Sysctl.NotFound += fmt.Sprintf("sysctl file for %s-%s-%s not found.<br>", targetBoard, targetMilestone, target)
		page.Sysctl.NotEmpty = true
	}
	if len(page.Sysctl.Changes) > 0 {
		page.Sysctl.NotEmpty = true
	}
	err = changelogTemplate.Execute(w, page)
	if err != nil {
		log.Errorf("error executing changelog template: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HandleFindBuild serves the Locate CL page
func HandleFindBuild(w http.ResponseWriter, r *http.Request) {
	if RequireToken(w, r, "/findbuild/") {
		return
	}
	var err error
	if err = r.ParseForm(); err != nil {
		err = findBuildTemplate.Execute(w, &findBuildPage{Internal: true})
		if err != nil {
			log.Errorf("error executing findbuild template: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
	cl := r.FormValue("cl")
	// If no CL value specified in request, display empty CL form
	if cl == "" {
		err = findBuildTemplate.Execute(w, &findBuildPage{Internal: true})
		if err != nil {
			log.Errorf("error executing findbuild template: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
	internal, gerrit, fallbackGerrit, gob, repo := false, externalGerritInstance, externalFallbackGerritInstance, externalGoBInstance, externalManifestRepo
	if r.FormValue("cos-internal") == "true" {
		internal, gerrit, fallbackGerrit, gob, repo = true, internalGerritInstance, internalFallbackGerritInstance, internalGoBInstance, internalManifestRepo
	}
	httpClient, err := HTTPClient(w, r)
	if err != nil {
		loginURL := GetLoginURL("/findbuild/", false)
		http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect)
		return
	}
	buildData, didFallback, utilErr := findBuildWithFallback(httpClient, gerrit, fallbackGerrit, gob, repo, cl, internal)
	if utilErr != nil {
		log.Errorf("error retrieving build for CL %s with internal set to %t\n%v", cl, internal, utilErr)
		handleError(w, r, utilErr, "/findbuild/")
		return
	}
	var gerritLink string
	if didFallback {
		gerritLink = fallbackGerrit + "/c/" + buildData.CLNum
	} else {
		gerritLink = gerrit + "/c/" + buildData.CLNum
	}
	page := &findBuildPage{
		CL:         cl,
		CLNum:      buildData.CLNum,
		BuildNum:   buildData.BuildNum,
		Internal:   internal,
		GerritLink: gerritLink,
	}
	err = findBuildTemplate.Execute(w, page)
	if err != nil {
		log.Errorf("error executing findbuild template: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HandleFindReleasedBuild serves the Locate CL page
func HandleFindReleasedBuild(w http.ResponseWriter, r *http.Request) {
	if RequireToken(w, r, "/findreleasedbuild/") { // TODO add findreleasebuild.html
		return
	}
	var err error
	if err = r.ParseForm(); err != nil {
		err = findReleasedBuildTemplate.Execute(w, &findBuildPage{Internal: true})
		if err != nil {
			log.Errorf("error executing findbuild template: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
	cl := r.FormValue("cl")
	// If no CL value specified in request, display empty CL form
	if cl == "" {
		err = findReleasedBuildTemplate.Execute(w, &findBuildPage{Internal: true})
		if err != nil {
			log.Errorf("error executing findreleasedbuild template: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
	internal, gerrit, gob, repo := false, externalGerritInstance, externalGoBInstance, externalManifestRepo
	if r.FormValue("cos-internal") == "true" {
		internal, gerrit, gob, repo = true, internalGerritInstance, internalGoBInstance, internalManifestRepo
	}
	httpClient, err := HTTPClient(w, r)
	if err != nil {
		loginURL := GetLoginURL("/findreleasedbuild/", false)
		http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect)
		return
	}
	buildData, utilErr := findReleaseBuild(httpClient, gerrit, gob, repo, cl, internal)
	if utilErr != nil {
		log.Errorf("error retrieving build for CL %s with internal set to %t\n%v", cl, internal, utilErr)
		handleError(w, r, utilErr, "/findreleasedbuild/")
		return
	}

	gerritLink := gerrit + "/c/" + buildData.CLNum

	page := &findBuildPage{
		CL:         cl,
		CLNum:      buildData.CLNum,
		BuildNum:   buildData.BuildNum,
		Internal:   internal,
		GerritLink: gerritLink,
	}
	err = findReleasedBuildTemplate.Execute(w, page)
	if err != nil {
		log.Errorf("error executing findreleasebuild template: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HandleFindReleasedBuildGerrit returns the released build number in JSON
func HandleFindReleasedBuildGerrit(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	if origin, ok := allowedOrigin(r.Header.Get("Origin")); ok {
		w.Header().Set("Access-Control-Allow-Origin", origin)
		w.Header().Set("Access-Control-Allow-Credentials", "true")
	}
	var err error
	if err = r.ParseForm(); err != nil {
		log.Errorf("error parsing form: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	cl := r.FormValue("cl")
	// If no CL value specified in request, display empty CL form
	if cl == "" {
		http.Error(w, "empty cl provided", http.StatusInternalServerError)
		return
	}
	internal, gerrit, gob, repo := false, externalGerritInstance, externalGoBInstance, externalManifestRepo
	if r.FormValue("cos-internal") == "true" {
		internal, gerrit, gob, repo = true, internalGerritInstance, internalGoBInstance, internalManifestRepo
	}
	buildData, utilErr := findReleaseBuild(nil, gerrit, gob, repo, cl, internal)
	if utilErr != nil {
		log.Errorf("error retrieving build for CL %s with internal set to %t\n%v", cl, internal, utilErr)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	versions := []string{}
	if buildData.BuildNum == "0.000.0" {
		versions = append(versions, "no build")
	} else {
		versions = append(versions, buildData.BuildNum)
	}
	json.NewEncoder(w).Encode(map[string][]string{"versions": versions})
}

func allowedOrigin(origin string) (string, bool) {
	if origin == "https://cos-review.googlesource.com" || origin == "https://cos-internal-review.googlesource.com" {
		return origin, true
	}
	return "", false
}
