// Copyright 2019 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"
	"sort"
	"strings"
	"testing"

	"github.com/google/go-cmp/cmp"
	"golang.org/x/pkgsite/internal/database"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/testing/sample"
	"golang.org/x/pkgsite/internal/version"
)

func TestDeleteModule(t *testing.T) {
	t.Parallel()
	testDB, release := acquire(t)
	defer release()
	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
	defer cancel()

	v := sample.DefaultModule()

	MustInsertModule(ctx, t, testDB, v)
	if _, err := testDB.GetModuleInfo(ctx, v.ModulePath, v.Version); err != nil {
		t.Fatal(err)
	}

	vm := sample.DefaultVersionMap()
	if err := testDB.UpsertVersionMap(ctx, vm); err != nil {
		t.Fatal(err)
	}
	if _, err := testDB.GetVersionMap(ctx, v.ModulePath, v.Version); err != nil {
		t.Fatal(err)
	}

	if err := testDB.DeleteModule(ctx, v.ModulePath, v.Version); err != nil {
		t.Fatal(err)
	}
	if _, err := testDB.GetModuleInfo(ctx, v.ModulePath, v.Version); !errors.Is(err, derrors.NotFound) {
		t.Errorf("got %v, want NotFound", err)
	}

	var x int
	err := testDB.Underlying().QueryRow(ctx, "SELECT 1 FROM imports_unique WHERE from_module_path = $1",
		v.ModulePath).Scan(&x)
	if err != sql.ErrNoRows {
		t.Errorf("imports_unique: got %v, want ErrNoRows", err)
	}
	err = testDB.Underlying().QueryRow(
		ctx,
		"SELECT 1 FROM version_map WHERE module_path = $1 AND resolved_version = $2",
		v.ModulePath, v.Version).Scan(&x)
	if err != sql.ErrNoRows {
		t.Errorf("version_map: got %v, want ErrNoRows", err)
	}
}

func TestDeleteFromSearch(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	const modulePath = "deleteme.com"

	initial := []searchDocumentRow{
		{modulePath + "/p1", modulePath, "v0.0.9", 0}, // oldest version of same module
		{modulePath + "/p2", modulePath, "v1.1.0", 0}, // older version of same module
		{modulePath + "/p4", modulePath, "v1.9.0", 0}, // newer version of same module
		{"other.org/p2", "other.org", "v1.1.0", 0},    // older version of a different module
	}

	insertInitial := func(db *DB) {
		t.Helper()
		for _, r := range initial {
			sm := sample.Module(r.ModulePath, r.Version, strings.TrimPrefix(r.PackagePath, r.ModulePath+"/"))
			MustInsertModule(ctx, t, db, sm)
		}
		// Older versions are deleted by InsertModule, so only the newest versions are here.
		checkSearchDocuments(ctx, t, db, initial[2:])
	}

	t.Run("deleteModuleFromSearchDocuments", func(t *testing.T) {
		// Non-empty list of packages tested above. This tests an empty list.
		testDB, release := acquire(t)
		defer release()
		insertInitial(testDB)

		if err := deleteModuleFromSearchDocuments(ctx, testDB.db, modulePath); err != nil {
			t.Fatal(err)
		}
		checkSearchDocuments(ctx, t, testDB, []searchDocumentRow{
			{"other.org/p2", "other.org", "v1.1.0", 0}, // other module not deleted
		})
	})
	t.Run("deleteOtherModulePackagesFromSearchDocuments", func(t *testing.T) {
		testDB, release := acquire(t)
		defer release()

		// Insert a module with two packages.
		m0 := sample.Module(modulePath, "v1.0.0", "p1", "p2")
		MustInsertModule(ctx, t, testDB, m0)
		// Set the imported-by count to a non-zero value so we can tell which
		// rows were deleted.
		if _, err := testDB.db.Exec(ctx, `UPDATE search_documents SET imported_by_count = 1`); err != nil {
			t.Fatal(err)
		}
		// Later version of module does not have p1.
		m1 := sample.Module(modulePath, "v1.1.0", "p2", "p3")
		MustInsertModule(ctx, t, testDB, m1)

		// p1 should be gone, p2 should be there with the same
		// imported_by_count, and p3 should be there with a zero count.
		want := []searchDocumentRow{
			{modulePath + "/p2", modulePath, "v1.1.0", 1},
			{modulePath + "/p3", modulePath, "v1.1.0", 0},
		}
		checkSearchDocuments(ctx, t, testDB, want)
	})
}

type searchDocumentRow struct {
	PackagePath, ModulePath, Version string
	ImportedByCount                  int
}

func readSearchDocuments(ctx context.Context, db *DB) ([]searchDocumentRow, error) {
	rows, err := database.CollectStructs[searchDocumentRow](ctx, db.db, `SELECT package_path, module_path, version, imported_by_count FROM search_documents`)
	if err != nil {
		return nil, err
	}
	return rows, err
}

func checkSearchDocuments(ctx context.Context, t *testing.T, db *DB, want []searchDocumentRow) {
	t.Helper()
	got, err := readSearchDocuments(ctx, db)
	if err != nil {
		t.Fatal(err)
	}
	less := func(r1, r2 searchDocumentRow) bool {
		if r1.PackagePath != r2.PackagePath {
			return r1.PackagePath < r2.PackagePath
		}
		if r1.ModulePath != r2.ModulePath {
			return r1.ModulePath < r2.ModulePath
		}
		return r1.Version < r2.Version
	}
	sort.Slice(got, func(i, j int) bool { return less(got[i], got[j]) })
	sort.Slice(want, func(i, j int) bool { return less(want[i], want[j]) })
	if diff := cmp.Diff(want, got); diff != "" {
		t.Errorf("search documents mismatch (-want, +got):\n%s", diff)
	}
}

func TestDeletePseudoversionsExcept(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	testDB, release := acquire(t)
	defer release()

	pseudo1 := "v0.0.0-20190904010203-89fb59e2e920"
	versions := []string{
		sample.VersionString,
		pseudo1,
		"v0.0.0-20190904010203-89fb59e2e920",
		"v0.0.0-20190904010203-89fb59e2e920",
	}
	for _, v := range versions {
		MustInsertModule(ctx, t, testDB, sample.Module(sample.ModulePath, v, ""))
	}
	if err := testDB.DeletePseudoversionsExcept(ctx, sample.ModulePath, pseudo1); err != nil {
		t.Fatal(err)
	}
	mods, err := getPathVersions(ctx, testDB, sample.ModulePath, version.TypeRelease)
	if err != nil {
		t.Fatal(err)
	}
	if len(mods) != 1 && mods[0].Version != sample.VersionString {
		t.Errorf("module version %q was not found", sample.VersionString)
	}
	mods, err = getPathVersions(ctx, testDB, sample.ModulePath, version.TypePseudo)
	if err != nil {
		t.Fatal(err)
	}
	if len(mods) != 1 {
		t.Fatalf("pseudoversions expected to be deleted were not")
	}
	if mods[0].Version != pseudo1 {
		t.Errorf("got %q; want %q", mods[0].Version, pseudo1)
	}
}
