// 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"
	"errors"
	"fmt"
	"sort"
	"strings"

	"github.com/lib/pq"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/database"
	"golang.org/x/pkgsite/internal/derrors"
)

// GetLatestMajorPathForV1Path reports the latest unit path in the series for
// the given v1path. It also returns the major version for that path.
func (db *DB) GetLatestMajorPathForV1Path(ctx context.Context, v1path string) (_ string, _ int, err error) {
	defer derrors.WrapStack(&err, "DB.GetLatestPathForV1Path(ctx, %q)", v1path)
	q := `
		SELECT p.path, m.series_path
		FROM paths p
		INNER JOIN units u ON u.path_id = p.id
		INNER JOIN modules m ON u.module_id = m.id
		WHERE u.v1path_id = (
			SELECT p.id
			FROM paths p
			INNER JOIN units u ON u.v1path_id = p.id
			WHERE p.path = $1
			ORDER BY p.path DESC
			LIMIT 1
		);`
	paths := map[string]string{} // from unit path to series path
	err = db.db.RunQuery(ctx, q, func(rows *sql.Rows) error {
		var p, sp string
		if err := rows.Scan(&p, &sp); err != nil {
			return err
		}
		paths[p] = sp
		return nil
	}, v1path)
	if err != nil {
		return "", 0, err
	}

	var (
		maj     int
		majPath string
	)
	for p, sp := range paths {
		// Trim the series path and suffix from the unit path.
		// Keep only the N following vN.
		suffix := internal.Suffix(v1path, sp)
		modPath := strings.TrimSuffix(p, "/"+suffix)
		_, i := internal.SeriesPathAndMajorVersion(modPath)
		if i == 0 {
			return "", 0, fmt.Errorf("bad module path %q", modPath)
		}
		if maj <= i {
			maj = i
			majPath = p
		}
	}
	if maj == 0 {
		// Return 1 as the major version for all v0 or v1 majPaths.
		maj = 1
	}
	return majPath, maj, nil
}

// upsertPath adds path into the paths table if it does not exist, and returns
// its ID either way.
// It assumes it is running inside a transaction.
func upsertPath(ctx context.Context, tx *database.DB, path string) (id int, err error) {
	// Doing the select first and then the insert led to uniqueness constraint
	// violations even with fully serializable transactions; see
	// https://www.postgresql.org/message-id/CAOqyxwL4E_JmUScYrnwd0_sOtm3bt4c7G%2B%2BUiD2PnmdGJFiqyQ%40mail.gmail.com.
	// If the upsert is done first and then the select, then everything works
	// fine.
	defer derrors.WrapStack(&err, "upsertPath(%q)", path)

	err = tx.QueryRow(ctx,
		`INSERT INTO paths (path) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id`,
		path).Scan(&id)
	if err == sql.ErrNoRows {
		err = tx.QueryRow(ctx,
			`SELECT id FROM paths WHERE path = $1`,
			path).Scan(&id)
		if err == sql.ErrNoRows {
			return 0, errors.New("got no rows; shouldn't happen")
		}
	}
	if err != nil {
		return 0, err
	}
	if id == 0 {
		return 0, errors.New("zero ID")
	}
	return id, nil
}

// upsertPaths adds all the paths to the paths table if they aren't already
// there, and returns their ID either way.
// It assumes it is running inside a transaction.
func upsertPaths(ctx context.Context, db *database.DB, paths []string) (pathToID map[string]int, err error) {
	defer derrors.WrapStack(&err, "upsertPaths(%d paths)", len(paths))

	// Read all existing paths for this module, to avoid a large bulk upsert.
	// (We've seen these bulk upserts hang for so long that they time out (10
	// minutes)).
	pathToID = map[string]int{}
	collect := func(rows *sql.Rows) error {
		var (
			pathID int
			path   string
		)
		if err := rows.Scan(&pathID, &path); err != nil {
			return err
		}
		pathToID[path] = pathID
		return nil
	}

	if err := db.RunQuery(ctx, `SELECT id, path FROM paths WHERE path = ANY($1)`,
		collect, pq.Array(paths)); err != nil {
		return nil, err
	}

	// Insert any unit paths that we don't already have.
	var values []any
	for _, v := range paths {
		if _, ok := pathToID[v]; !ok {
			values = append(values, v)
		}
	}
	if len(values) > 0 {
		// Sort to avoid deadlock.
		sort.Slice(values, func(i, j int) bool { return values[i].(string) < values[j].(string) })
		// Insert data into the paths table.
		pathCols := []string{"path"}
		returningPathCols := []string{"id", "path"}
		if err := db.BulkInsertReturning(ctx, "paths", pathCols, values,
			database.OnConflictDoNothing, returningPathCols, collect); err != nil {
			return nil, err
		}
	}
	return pathToID, nil
}

func GetPathID(ctx context.Context, ddb *database.DB, path string) (id int, err error) {
	err = ddb.QueryRow(ctx,
		`SELECT id FROM paths WHERE path = $1`,
		path).Scan(&id)
	return id, err
}
