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

package postgres

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/Masterminds/squirrel"
	"github.com/lib/pq"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/database"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/experiment"
	"golang.org/x/pkgsite/internal/middleware"
)

// getPackageSymbols returns all of the symbols for a given package path and module path.
func getPackageSymbols(ctx context.Context, ddb *database.DB, packagePath, modulePath string,
) (_ *internal.SymbolHistory, err error) {
	defer derrors.Wrap(&err, "getPackageSymbols(ctx, ddb, %q, %q)", packagePath, modulePath)
	defer middleware.ElapsedStat(ctx, "getPackageSymbols")()

	query := packageSymbolQueryJoin(
		squirrel.Select(
			"s1.name AS symbol_name",
			"s2.name AS parent_symbol_name",
			"ps.section",
			"ps.type",
			"ps.synopsis",
			"m.version",
			"d.goos",
			"d.goarch"), packagePath, modulePath).
		OrderBy("CASE WHEN ps.type='Type' THEN 0 ELSE 1 END").
		OrderBy("s1.name")
	q, args, err := query.PlaceholderFormat(squirrel.Dollar).ToSql()
	if err != nil {
		return nil, err
	}
	sh, collect := collectSymbolHistory(func(sh *internal.SymbolHistory, sm internal.SymbolMeta, v string, build internal.BuildContext) error {
		if sm.Section == internal.SymbolSectionTypes && sm.Kind != internal.SymbolKindType {
			_, err := sh.GetSymbol(sm.ParentName, v, build)
			if err != nil {
				return fmt.Errorf("could not find parent for %q: %v", sm.Name, err)
			}
			return nil
		}
		return nil
	})
	if err := ddb.RunQuery(ctx, q, collect, args...); err != nil {
		return nil, err
	}
	return sh, nil
}

func packageSymbolQueryJoin(query squirrel.SelectBuilder, pkgPath, modulePath string) squirrel.SelectBuilder {
	return query.From("modules m").
		Join("units u on u.module_id = m.id").
		Join("documentation d ON d.unit_id = u.id").
		Join("documentation_symbols ds ON ds.documentation_id = d.id").
		Join("package_symbols ps ON ps.id = ds.package_symbol_id").
		Join("paths p1 ON u.path_id = p1.id").
		Join("symbol_names s1 ON ps.symbol_name_id = s1.id").
		Join("symbol_names s2 ON ps.parent_symbol_name_id = s2.id").
		Where(squirrel.Eq{"p1.path": pkgPath}).
		Where(squirrel.Eq{"m.module_path": modulePath}).
		Where("NOT m.incompatible").
		Where(squirrel.Eq{"m.version_type": "release"})
}

func collectSymbolHistory(check func(sh *internal.SymbolHistory, sm internal.SymbolMeta, v string, build internal.BuildContext) error) (*internal.SymbolHistory, func(rows *sql.Rows) error) {
	sh := internal.NewSymbolHistory()
	return sh, func(rows *sql.Rows) (err error) {
		defer derrors.Wrap(&err, "collectSymbolHistory")
		var (
			sm    internal.SymbolMeta
			build internal.BuildContext
			v     string
		)
		if err := rows.Scan(
			&sm.Name,
			&sm.ParentName,
			&sm.Section,
			&sm.Kind,
			&sm.Synopsis,
			&v,
			&build.GOOS,
			&build.GOARCH,
		); err != nil {
			return fmt.Errorf("row.Scan(): %v", err)
		}
		if err := check(sh, sm, v, build); err != nil {
			return fmt.Errorf("check(): %v", err)
		}
		sh.AddSymbol(sm, v, build)
		return nil
	}
}

func upsertSearchDocumentSymbols(ctx context.Context, ddb *database.DB,
	packagePath, modulePath, v string) (err error) {
	defer derrors.Wrap(&err, "upsertSearchDocumentSymbols(ctx, ddb, %q, %q, %q)", packagePath, modulePath, v)
	defer middleware.ElapsedStat(ctx, "upsertSearchDocumentSymbols")()

	if !experiment.IsActive(ctx, internal.ExperimentInsertSymbolSearchDocuments) {
		return nil
	}

	// If a user is looking for the symbol "DB.Begin", from package
	// database/sql, we want them to be able to find this by searching for
	// "DB.Begin" and "sql.DB.Begin". Searching for "sql.DB", "DB", "Begin" or
	// "sql.DB" will not return "DB.Begin".
	query := packageSymbolQueryJoin(squirrel.Select(
		"p1.id AS package_path_id",
		"s1.id AS symbol_name_id",
		// Group the build contexts as an array, with the format
		// "<goos>/<goarch>". We only care about the build contexts when the
		// default goos/goarch for the package page does not contain the
		// matching symbol.
		//
		// TODO(https://golang/issue/44142): We could probably get away with
		// storing just the GOOS value, since we don't really need the GOARCH
		// to link to a symbol page. If we do that we should also change the
		// column type to []goos.
		//
		// Store in order of the build context list at internal.BuildContexts.
		`ARRAY_AGG(FORMAT('%s/%s', d.goos, d.goarch)
			ORDER BY
				CASE WHEN d.goos='linux' THEN 0
				WHEN d.goos='windows' THEN 1
				WHEN d.goos='darwin' THEN 2
				WHEN d.goos='js' THEN 3 END)`,
		// If a user is looking for the symbol "DB.Begin", from package
		// database/sql, we want them to be able to find this by searching for
		// "DB.Begin", "Begin", and "sql.DB.Begin". Searching for "sql.DB" or
		// "DB" will not return "DB.Begin".
		//
		// Index <package>.<identifier> (i.e. "sql.DB.Begin")
		`SETWEIGHT(
			TO_TSVECTOR('simple', concat(s1.name, ' ', concat(u.name, '.', s1.name))),
			'A') ||`+
			// Index <identifier>, including the parent name (i.e. DB.Begin).
			`SETWEIGHT(
				TO_TSVECTOR('simple', s1.name),
				'A') ||`+
			// Index <identifier> without parent name (i.e. "Begin").
			//
			// This is weighted less, so that if other symbols are just named
			// "Begin" they will rank higher in a search for "Begin".
			`SETWEIGHT(
				TO_TSVECTOR('simple', split_part(s1.name, '.', 2)),
				'B') AS tokens`,
	), packagePath, modulePath).
		Where(squirrel.Eq{"m.version": v}).
		GroupBy("p1.id, s1.id", "tokens").
		OrderBy("s1.name")

	q, args, err := query.PlaceholderFormat(squirrel.Dollar).ToSql()
	if err != nil {
		return err
	}

	var values []interface{}
	collect := func(rows *sql.Rows) (err error) {
		var (
			packagePathID int
			symbolNameID  int
			tokens        string
			buildContexts []string
		)
		if err := rows.Scan(
			&packagePathID,
			&symbolNameID,
			pq.Array(&buildContexts),
			&tokens,
		); err != nil {
			return fmt.Errorf("row.Scan(): %v", err)
		}
		values = append(values, packagePathID, symbolNameID, pq.Array(buildContexts), tokens)
		return nil
	}
	if err := ddb.RunQuery(ctx, q, collect, args...); err != nil {
		return err
	}

	columns := []string{"package_path_id", "symbol_name_id", "build_contexts", "tsv_symbol_tokens"}
	return ddb.BulkInsert(ctx, "symbol_search_documents", columns, values,
		`ON CONFLICT (package_path_id, symbol_name_id)
				DO UPDATE
				SET
					build_contexts=excluded.build_contexts,
					tsv_symbol_tokens=excluded.tsv_symbol_tokens`)
}
