// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The search command is used to run tests for search using a dataset of
// modules specified at tests/search/seed.txt.
// See tests/README.md for details.
package main

import (
	"bufio"
	"context"
	"flag"
	"fmt"
	"os"
	"strconv"
	"strings"

	_ "github.com/jackc/pgx/v4/stdlib" // for pgx driver
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/config"
	"golang.org/x/pkgsite/internal/database"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/experiment"
	"golang.org/x/pkgsite/internal/log"
	"golang.org/x/pkgsite/internal/postgres"
)

func main() {
	flag.Parse()

	ctx := experiment.NewContext(context.Background(), symbolSearchExperiments...)
	cfg, err := config.Init(ctx)
	if err != nil {
		log.Fatal(ctx, err)
	}
	log.SetLevel(cfg.LogLevel)

	// Wrap the postgres driver with our own wrapper, which adds OpenCensus instrumentation.
	ddb, err := database.Open("pgx", cfg.DBConnInfo(), "seeddb")
	if err != nil {
		log.Fatalf(ctx, "database.Open for host %s failed with %v", cfg.DBHost, err)
	}
	db := postgres.New(ddb)
	defer db.Close()

	if err := run(ctx, db); err != nil {
		log.Fatal(ctx, err)
	}
}

const (
	importedbyFile = "tests/search/importedby.txt"
	testFile       = "tests/search/scripts/symbolsearch.txt"
)

var symbolSearchExperiments = []string{
	internal.ExperimentInsertSymbolSearchDocuments,
	internal.ExperimentSearchGrouping,
	internal.ExperimentSymbolSearch,
}

func run(ctx context.Context, db *postgres.DB) error {
	counts, err := readImportedByCounts(importedbyFile)
	if err != nil {
		return err
	}
	if _, err := db.UpdateSearchDocumentsImportedByCountWithCounts(ctx, counts); err != nil {
		return err
	}
	tests, err := readSearchTests(testFile)
	if err != nil {
		return err
	}
	var failed bool
	for _, st := range tests {
		output, err := runTest(ctx, db, st)
		if err != nil {
			return err
		}
		if len(output) == 0 {
			fmt.Println("--- PASSED: ", st.title)
			continue
		}
		failed = true
		fmt.Println("--- FAILED: ", st.title)
		for _, e := range output {
			fmt.Println(e)
		}
	}
	if failed {
		return fmt.Errorf("SEARCH TESTS FAILED: see output above")
	}
	return nil
}

func runTest(ctx context.Context, db *postgres.DB, st *searchTest) (output []string, err error) {
	defer derrors.Wrap(&err, "runTest(ctx, db, st.title: %q)", st.title)
	results, err := db.Search(ctx, st.query, postgres.SearchOptions{MaxResults: 10, SearchSymbols: true})
	if err != nil {
		return nil, err
	}
	for i, want := range st.results {
		got := &postgres.SearchResult{}
		if len(results) > i {
			got = results[i]
		}
		if want.symbol != got.SymbolName || want.pkg != got.PackagePath {
			output = append(output,
				fmt.Sprintf("query %s, mismatch result %d:\n\twant: %q %q\n\t got: %q %q\n",
					st.query, i+1,
					want.pkg, want.symbol,
					got.PackagePath, got.SymbolName))
		}
	}
	return output, nil
}

type searchTest struct {
	title   string
	query   string
	results []*searchResult
}

type searchResult struct {
	pkg    string
	symbol string
}

// readSearchTests reads filename and returns the search tests from that file.
// See tests/README.md for a description of the syntax.
func readSearchTests(filename string) ([]*searchTest, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	scan := bufio.NewScanner(f)

	var (
		tests []*searchTest
		test  searchTest
		num   int
		curr  = posNewline
	)
	for scan.Scan() {
		num += 1
		line := strings.TrimSpace(scan.Text())

		var prefix string
		if len(line) > 0 {
			prefix = string(line[0])
		}
		switch prefix {
		case "#":
			// Skip comment lines.
			continue
		case "":
			// Each set of tests is separated by a newline. Before a newline, we must
			// have passed a test case result, another newline, or a comment,
			// otherwise this file can't be valid.
			if curr != posNewline && curr != posResult {
				return nil, fmt.Errorf("invalid syntax on line %d: %q", num, line)
			}
			if curr == posResult {
				// This is the first time that we have seen a newline for this
				// test set. Now that we know the test set is complete, append
				// it to the array of tests, and reset test to an empty
				// searchTest struct.
				t2 := test
				tests = append(tests, &t2)
				test = searchTest{}
			}
			curr = posNewline
		default:
			switch curr {
			case posNewline:
				// The last position was a newline, so this must be the start
				// of a new test set.
				curr = posTitle
				test.title = line
			case posTitle:
				// The last position was a title, so this must be the start
				// of a new test set.
				curr = posQuery
				test.query = line
			case posQuery, posResult:
				// The last position was a query or a result, so this must be
				// an expected search result.
				curr = posResult
				parts := strings.Split(line, " ")
				if len(parts) != 2 {
					return nil, fmt.Errorf("invalid syntax on line %d: %q", num, line)
				}
				r := &searchResult{
					symbol: parts[0],
					pkg:    parts[1],
				}
				test.results = append(test.results, r)
			default:
				// We should never reach this error.
				return nil, fmt.Errorf("invalid syntax on line %d: %q", num, line)
			}
		}
	}
	if err := scan.Err(); err != nil {
		return nil, fmt.Errorf("scan.Err(): %v", err)
	}
	tests = append(tests, &test)
	return tests, nil
}

// readSearchTests reads filename and returns a map of package path to imported
// by count. See tests/README.md for a description of the syntax.
func readImportedByCounts(filename string) (map[string]int, error) {
	counts := map[string]int{}
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	scan := bufio.NewScanner(f)
	for scan.Scan() {
		line := strings.TrimSpace(scan.Text())
		if line == "" || line[0] == '#' {
			continue
		}
		parts := strings.SplitN(line, ", ", 2)
		c, err := strconv.Atoi(parts[1])
		if err != nil {
			return nil, err
		}
		counts[parts[0]] = c
	}
	if err := scan.Err(); err != nil {
		return nil, err
	}
	return counts, nil
}

const (
	posNewline = 1 << iota
	posTitle
	posQuery
	posResult
)
