// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package common

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"

	"dawn.googlesource.com/dawn/tools/src/buildbucket"
	"dawn.googlesource.com/dawn/tools/src/cts/query"
	"dawn.googlesource.com/dawn/tools/src/cts/result"
	"dawn.googlesource.com/dawn/tools/src/fileutils"
	"dawn.googlesource.com/dawn/tools/src/gerrit"
	"dawn.googlesource.com/dawn/tools/src/resultsdb"
	"dawn.googlesource.com/dawn/tools/src/subcmd"
	"go.chromium.org/luci/auth"
	rdbpb "go.chromium.org/luci/resultdb/proto/v1"
)

// These function signatures are to facilitate code reuse between the code paths
// for getting all results and for only getting unsuppressed failures.
// For MostRecentResultsForChange/MostRecentUnsuppressedFailingResultsForChange.
type mostRecentResultsFunc = func(context.Context, Config, string, *gerrit.Gerrit, *buildbucket.Buildbucket, resultsdb.Querier, int) (result.ResultsByExecutionMode, gerrit.Patchset, error)

// For CacheResults/CacheUnsuppressedFailingResults.
type cacheResultsFunc = func(context.Context, Config, gerrit.Patchset, string, resultsdb.Querier, BuildsByName) (result.ResultsByExecutionMode, error)

// For GetRawResults/GetRawUnsuppressedFailingResults.
type getRawResultsFunc = func(context.Context, Config, resultsdb.Querier, BuildsByName) (result.ResultsByExecutionMode, error)

// ResultSource describes the source of CTS test results.
// ResultSource is commonly used by command line flags for specifying from
// where the results should be loaded / fetched.
// If neither File or Patchset are specified, then results will be fetched from
// the last successful CTS roll.
type ResultSource struct {
	// The directory used to cache results fetched from ResultDB
	CacheDir string
	// If specified, results will be loaded from this file path
	// Must not be specified if Patchset is also specified.
	File string
	// If specified, results will be fetched from this gerrit patchset
	// Must not be specified if File is also specified.
	Patchset gerrit.Patchset
}

// RegisterFlags registers the ResultSource fields as commandline flags for use
// by command line tools.
func (r *ResultSource) RegisterFlags(cfg Config) {
	flag.StringVar(&r.CacheDir, "cache", DefaultCacheDir, "path to the results cache")
	flag.StringVar(&r.File, "results", "", "local results.txt file (mutually exclusive with --cl)")
	r.Patchset.RegisterFlags(cfg.Gerrit.Host, cfg.Gerrit.Project)
}

// GetResults loads or fetches the results, based on the values of r.
// GetResults will update the ResultSource with the inferred patchset, if a file
// and specific patchset was not specified.
func (r *ResultSource) GetResults(ctx context.Context, cfg Config, auth auth.Options) (result.ResultsByExecutionMode, error) {
	return r.getResultsImpl(ctx, cfg, auth, MostRecentResultsForChange, CacheResults)
}

// GetUnsuppressedFailingResults loads or fetches the unsuppressed failing
// results, based on the values of r.
// GetUnsuppressedFailingResults will update the ResultSource with the inferred
// patchset if a file and specific patchset was not specified.
func (r *ResultSource) GetUnsuppressedFailingResults(ctx context.Context, cfg Config, auth auth.Options) (result.ResultsByExecutionMode, error) {
	return r.getResultsImpl(ctx, cfg, auth, MostRecentUnsuppressedFailingResultsForChange, CacheUnsuppressedFailingResults)
}

// Helper function to share the implementation between GetResults and GetUnsuppressedFailingResults.
func (r *ResultSource) getResultsImpl(ctx context.Context, cfg Config, auth auth.Options,
	getRecentResults mostRecentResultsFunc, cacheResults cacheResultsFunc) (result.ResultsByExecutionMode, error) {
	// Check that File and Patchset weren't both specified
	ps := &r.Patchset
	if r.File != "" && ps.Change != 0 {
		fmt.Fprintln(flag.CommandLine.Output(), "only one of --results and --cl can be specified")
		return nil, subcmd.ErrInvalidCLA
	}

	// If a file was specified, then load that.
	if r.File != "" {
		return result.Load(r.File)
	}

	// Initialize the buildbucket and resultdb clients
	bb, err := buildbucket.New(ctx, auth)
	if err != nil {
		return nil, err
	}
	client, err := resultsdb.NewBigQueryClient(ctx, resultsdb.DefaultQueryProject)
	if err != nil {
		return nil, err
	}

	// If no change was specified, then pull the results from the most recent
	// CTS roll.
	if ps.Change == 0 {
		fmt.Println("no change specified, scanning gerrit for last CTS roll...")
		gerrit, err := gerrit.New(ctx, auth, cfg.Gerrit.Host)
		if err != nil {
			return nil, err
		}
		latest, err := LatestCTSRoll(gerrit)
		if err != nil {
			return nil, err
		}
		fmt.Printf("scanning for latest patchset of %v...\n", latest.Number)
		var resultsByExecutionMode result.ResultsByExecutionMode
		resultsByExecutionMode, *ps, err = getRecentResults(ctx, cfg, r.CacheDir, gerrit, bb, client, latest.Number)
		if err != nil {
			return nil, err
		}
		fmt.Printf("using results from cl %v ps %v...\n", ps.Change, ps.Patchset)
		return resultsByExecutionMode, nil
	}

	// If a change, but no patchset was specified, then query the most recent
	// patchset.
	if ps.Patchset == 0 {
		gerrit, err := gerrit.New(ctx, auth, cfg.Gerrit.Host)
		if err != nil {
			return nil, err
		}
		*ps, err = gerrit.LatestPatchset(strconv.Itoa(ps.Change))
		if err != nil {
			err := fmt.Errorf("failed to find latest patchset of change %v: %w",
				ps.Change, err)
			return nil, err
		}
	}

	// Obtain the patchset's results, kicking a build if there are no results
	// already available.
	builds, err := GetOrStartBuildsAndWait(ctx, cfg, *ps, bb, "", false)
	if err != nil {
		return nil, err
	}

	resultsByExecutionMode, err := cacheResults(ctx, cfg, *ps, r.CacheDir, client, builds)
	if err != nil {
		return nil, err
	}

	return resultsByExecutionMode, nil
}

// CacheResults looks in the cache at 'cacheDir' for the results for the given patchset.
// If the cache contains the results, then these are loaded, transformed with CleanResults() and
// returned.
// If the cache does not contain the results, then they are fetched using GetRawResults(), saved to
// the cache directory, transformed with CleanResults() and then returned.
func CacheResults(
	ctx context.Context,
	cfg Config,
	ps gerrit.Patchset,
	cacheDir string,
	client resultsdb.Querier,
	builds BuildsByName) (result.ResultsByExecutionMode, error) {

	return cacheResultsImpl(ctx, cfg, ps, cacheDir, "", client, builds, GetRawResults)
}

// CacheUnsuppressedFailingResults looks in the cache at 'cacheDir' for the
// unsuppressed failing results for the given patchset. If the cache contains
// the results, then these are loaded, transformed with CleanResults(), and
// returned.
// If the cache does not contain the results, then they are fetched using
// GetRawUnsuppressedFailingResults(), saved to the cache directory, transformed
// with CleanResults(), and then returned.
func CacheUnsuppressedFailingResults(
	ctx context.Context,
	cfg Config,
	ps gerrit.Patchset,
	cacheDir string,
	client resultsdb.Querier,
	builds BuildsByName) (result.ResultsByExecutionMode, error) {

	return cacheResultsImpl(ctx, cfg, ps, cacheDir, "-unsuppressed-failures", client, builds, GetRawUnsuppressedFailingResults)
}

// Helper function to share the implementation between CacheResults and CacheUnsuppressedFailingResults.
func cacheResultsImpl(
	ctx context.Context,
	cfg Config,
	ps gerrit.Patchset,
	cacheDir string,
	fileSuffix string,
	client resultsdb.Querier,
	builds BuildsByName,
	getRawResults getRawResultsFunc) (result.ResultsByExecutionMode, error) {

	var cachePath string
	if cacheDir != "" {
		dir := fileutils.ExpandHome(cacheDir)
		path := filepath.Join(dir, strconv.Itoa(ps.Change), fmt.Sprintf("ps-%v%v.txt", ps.Patchset, fileSuffix))
		if _, err := os.Stat(path); err == nil {
			log.Printf("loading cached results from cl %v ps %v...", ps.Change, ps.Patchset)
			return result.Load(path)
		}
		cachePath = path
	}

	log.Printf("fetching results from cl %v ps %v...", ps.Change, ps.Patchset)
	resultsByExecutionMode, err := getRawResults(ctx, cfg, client, builds)
	if err != nil {
		return nil, err
	}

	if err := result.Save(cachePath, resultsByExecutionMode); err != nil {
		log.Println("failed to save results to cache: %w", err)
	}

	// Expand aliased tags, remove specific tags
	for i, results := range resultsByExecutionMode {
		CleanResults(cfg, &results)
		results.Sort()
		resultsByExecutionMode[i] = results
	}

	return resultsByExecutionMode, nil
}

// GetResults calls GetRawResults() to fetch the build results from ResultDB and applies CleanResults().
// GetResults does not trigger new builds.
func GetResults(
	ctx context.Context,
	cfg Config,
	client resultsdb.Querier,
	builds BuildsByName) (result.ResultsByExecutionMode, error) {

	return getResultsImpl(ctx, cfg, client, builds, GetRawResults)
}

// GetUnsuppressedFailingResults calls GetRawUnsuppressedFailingResults() to
// fetch the unsuppressed failing results from ResultDB and applies
// CleanResults(). GetUnsuppressedFailingResults() does not trigger new builds.
func GetUnsuppressedFailingResults(
	ctx context.Context,
	cfg Config,
	client resultsdb.Querier,
	builds BuildsByName) (result.ResultsByExecutionMode, error) {

	return getResultsImpl(ctx, cfg, client, builds, GetRawUnsuppressedFailingResults)
}

// Helper function to share the implementation between GetResults and GetUnsuppressedFailingResults.
func getResultsImpl(
	ctx context.Context,
	cfg Config,
	client resultsdb.Querier,
	builds BuildsByName,
	getRawResults getRawResultsFunc) (result.ResultsByExecutionMode, error) {

	resultsByExecutionMode, err := getRawResults(ctx, cfg, client, builds)
	if err != nil {
		return nil, err
	}

	// Expand aliased tags, remove specific tags
	for i, results := range resultsByExecutionMode {
		CleanResults(cfg, &results)
		results.Sort()
		resultsByExecutionMode[i] = results
	}

	return resultsByExecutionMode, err
}

// GetRawResults fetches the build results from ResultDB, without applying CleanResults().
// GetRawResults does not trigger new builds.
func GetRawResults(
	ctx context.Context,
	cfg Config,
	client resultsdb.Querier,
	builds BuildsByName) (result.ResultsByExecutionMode, error) {

	return getRawResultsImpl(ctx, cfg, client, builds, client.QueryTestResults)
}

// GetRawUnsuppressedFailingResults fetches the unsuppressed failing results
// from ResultDB, without applying CleanResults().
// GetRawUnsuppressedFailingResults does not trigger new builds.
func GetRawUnsuppressedFailingResults(
	ctx context.Context,
	cfg Config,
	client resultsdb.Querier,
	builds BuildsByName) (result.ResultsByExecutionMode, error) {

	return getRawResultsImpl(ctx, cfg, client, builds, client.QueryUnsuppressedFailingTestResults)
}

// Helper function to share the implementation between GetRawResults and
// GetRawUnsuppressedFailingResults.
func getRawResultsImpl(
	ctx context.Context,
	cfg Config,
	client resultsdb.Querier,
	builds BuildsByName,
	queryFunc resultsdb.QueryFunc) (result.ResultsByExecutionMode, error) {

	fmt.Printf("fetching results from resultdb...")

	lastPrintedDot := time.Now()

	toStatus := func(s string) result.Status {
		switch s {
		default:
			return result.Unknown
		case rdbpb.TestStatus_PASS.String():
			return result.Pass
		case rdbpb.TestStatus_FAIL.String():
			return result.Failure
		case rdbpb.TestStatus_CRASH.String():
			return result.Crash
		case rdbpb.TestStatus_ABORT.String():
			return result.Abort
		case rdbpb.TestStatus_SKIP.String():
			return result.Skip
		}
	}

	resultsByExecutionMode := result.ResultsByExecutionMode{}
	for _, test := range cfg.Tests {
		results := result.List{}
		for _, prefix := range test.Prefixes {

			err := queryFunc(ctx, builds.ids(), prefix, func(r *resultsdb.QueryResult) error {
				if time.Since(lastPrintedDot) > 5*time.Second {
					lastPrintedDot = time.Now()
					fmt.Printf(".")
				}

				if !strings.HasPrefix(r.TestId, prefix) {
					return errors.New(fmt.Sprintf("Test ID %s did not start with %s even though query should have filtered.", r.TestId, prefix))
				}

				testName := r.TestId[len(prefix):]
				status := toStatus(r.Status)
				tags := result.NewTags()
				duration := time.Duration(r.Duration * float64(time.Second))
				mayExonerate := false

				for _, tagPair := range r.Tags {
					if tagPair.Key == "typ_tag" {
						tags.Add(tagPair.Value)
					} else if tagPair.Key == "javascript_duration" {
						var err error
						if duration, err = time.ParseDuration(tagPair.Value); err != nil {
							return err
						}
					} else if tagPair.Key == "may_exonerate" {
						var err error
						if mayExonerate, err = strconv.ParseBool(tagPair.Value); err != nil {
							return err
						}
					}
				}

				results = append(results, result.Result{
					Query:        query.Parse(testName),
					Status:       status,
					Tags:         tags,
					Duration:     duration,
					MayExonerate: mayExonerate,
				})

				return nil
			})

			if err != nil {
				return nil, err
			}

			results.Sort()
		}
		resultsByExecutionMode[test.ExecutionMode] = results
	}

	fmt.Println(" done")

	return resultsByExecutionMode, nil
}

// LatestCTSRoll returns for the latest merged CTS roll that landed in the past
// month. If no roll can be found, then an error is returned.
func LatestCTSRoll(g *gerrit.Gerrit) (gerrit.ChangeInfo, error) {
	changes, _, err := g.QueryChanges(
		`status:merged`,
		`-age:1month`,
		fmt.Sprintf(`message:"%v"`, RollSubjectPrefix))
	if err != nil {
		return gerrit.ChangeInfo{}, err
	}
	if len(changes) == 0 {
		return gerrit.ChangeInfo{}, fmt.Errorf("no change found")
	}
	sort.Slice(changes, func(i, j int) bool {
		return changes[i].Submitted.Time.After(changes[j].Submitted.Time)
	})
	return changes[0], nil
}

// LatestPatchset returns the most recent patchset for the given change.
func LatestPatchset(g *gerrit.Gerrit, change int) (gerrit.Patchset, error) {
	ps, err := g.LatestPatchset(strconv.Itoa(change))
	if err != nil {
		err := fmt.Errorf("failed to find latest patchset of change %v: %w",
			ps.Change, err)
		return gerrit.Patchset{}, err
	}
	return ps, nil
}

// MostRecentResultsForChange returns the results from the most recent patchset
// that has build results. If no results can be found for the entire change,
// then an error is returned.
func MostRecentResultsForChange(
	ctx context.Context,
	cfg Config,
	cacheDir string,
	g *gerrit.Gerrit,
	bb *buildbucket.Buildbucket,
	client resultsdb.Querier,
	change int) (result.ResultsByExecutionMode, gerrit.Patchset, error) {

	return mostRecentResultsForChangeImpl(ctx, cfg, cacheDir, g, bb, client, change, CacheResults)
}

// MostRecentUnsuppressedFailingResultsForChange returns the unsuppressed
// failing results from the most recent patchset that has build results. If no
// results can be found for the entire change, then an error is returned.
func MostRecentUnsuppressedFailingResultsForChange(
	ctx context.Context,
	cfg Config,
	cacheDir string,
	g *gerrit.Gerrit,
	bb *buildbucket.Buildbucket,
	client resultsdb.Querier,
	change int) (result.ResultsByExecutionMode, gerrit.Patchset, error) {

	return mostRecentResultsForChangeImpl(ctx, cfg, cacheDir, g, bb, client, change, CacheUnsuppressedFailingResults)
}

// Helper function to share the implementation between MostRecentResultsForChange
// and MostRecentUnsuppressedFailingResultsForChange.
func mostRecentResultsForChangeImpl(
	ctx context.Context,
	cfg Config,
	cacheDir string,
	g *gerrit.Gerrit,
	bb *buildbucket.Buildbucket,
	client resultsdb.Querier,
	change int,
	cacheResults cacheResultsFunc) (result.ResultsByExecutionMode, gerrit.Patchset, error) {

	ps, err := LatestPatchset(g, change)
	if err != nil {
		return nil, gerrit.Patchset{}, nil
	}

	for ps.Patchset > 0 {
		builds, err := GetBuilds(ctx, cfg, ps, bb)
		if err != nil {
			return nil, gerrit.Patchset{}, err
		}
		if len(builds) > 0 {
			if err := WaitForBuildsToComplete(ctx, cfg, ps, bb, builds); err != nil {
				return nil, gerrit.Patchset{}, err
			}

			results, err := cacheResults(ctx, cfg, ps, cacheDir, client, builds)
			if err != nil {
				return nil, gerrit.Patchset{}, err
			}

			if len(results) > 0 {
				return results, ps, nil
			}
		}
		ps.Patchset--
	}

	return nil, gerrit.Patchset{}, fmt.Errorf("no builds found for change %v", change)
}

// CleanResults modifies each result so that tags in cfg.Tag.Remove are removed and
// duplicate results are removed by erring towards Failure.
// See: crbug.com/dawn/1387, crbug.com/dawn/1401
func CleanResults(cfg Config, results *result.List) {
	// Remove any tags found in cfg.Tag.Remove
	remove := result.NewTags(cfg.Tag.Remove...)
	for _, r := range *results {
		r.Tags.RemoveAll(remove)
	}
	// Clean up duplicate results
	*results = results.ReplaceDuplicates(func(s result.Statuses) result.Status {
		// If all results have the same status, then use that.
		if len(s) == 1 {
			return s.One()
		}
		// Mixed statuses. Replace with something appropriate.
		switch {
		case s.Contains(result.Crash):
			return result.Crash
		case s.Contains(result.Abort):
			return result.Abort
		case s.Contains(result.Failure):
			return result.Failure
		case s.Contains(result.Slow):
			return result.Slow
		}
		return result.Failure
	})
}
