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

import (
	"context"
	"errors"
	"io"
	"io/fs"
	"os"
	"path/filepath"
	"testing"
	"time"

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

func TestDirectoryModuleGetterEmpty(t *testing.T) {
	g, err := NewDirectoryModuleGetter("", "testdata/has_go_mod")
	if err != nil {
		t.Fatal(err)
	}
	if want := "example.com/testmod"; g.modulePath != want {
		t.Errorf("got %q, want %q", g.modulePath, want)
	}

	_, err = NewDirectoryModuleGetter("", "testdata/no_go_mod")
	if !errors.Is(err, derrors.BadModule) {
		t.Errorf("got %v, want BadModule", err)
	}
}

const multiModule = `
-- go.work --
go 1.21

use (
	./foo
	./bar
)

-- foo/go.mod --
module foo.com/foo

go 1.21
-- foo/foolog/f.go --
package foolog

const Log = 1
-- bar/go.mod --
module bar.com/bar

go 1.20
-- bar/barlog/b.go --
package barlog

const Log = 1
`

func TestGoPackagesModuleGetter(t *testing.T) {
	modulePaths := map[string]string{ // dir -> module path
		"foo": "foo.com/foo",
		"bar": "bar.com/bar",
	}

	tests := []struct {
		name string
		dir  string
	}{
		{"work dir", "."},
		{"module dir", "foo"},
		{"nested package dir", "foo/foolog"},
	}

	ctx := context.Background()
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			tempDir, files := testhelper.WriteTxtarToTempDir(t, multiModule)
			dir := filepath.Join(tempDir, test.dir)

			g, err := NewGoPackagesModuleGetter(ctx, dir, "all")
			if err != nil {
				t.Fatal(err)
			}

			for moduleDir, modulePath := range modulePaths {
				t.Run("info", func(t *testing.T) {
					got, err := g.Info(ctx, modulePath, "")
					if err != nil {
						t.Fatal(err)
					}
					if got, want := got.Version, LocalVersion; got != want {
						t.Errorf("Info(%s): got version %s, want %s", modulePath, got, want)
					}
				})

				mod := files[moduleDir+"/go.mod"]
				t.Run("mod", func(t *testing.T) {
					got, err := g.Mod(ctx, modulePath, "")
					if err != nil {
						t.Fatal(err)
					}
					if diff := cmp.Diff(mod, string(got)); diff != "" {
						t.Errorf("Mod(%q) mismatch [-want +got]:\n%s", modulePath, diff)
					}
				})

				t.Run("contentdir", func(t *testing.T) {
					fsys, err := g.ContentDir(ctx, modulePath, "")
					if err != nil {
						t.Fatal(err)
					}
					// Just check that the go.mod file is there and has the right contents.
					got, err := fs.ReadFile(fsys, "go.mod")
					if err != nil {
						t.Fatal(err)
					}
					if diff := cmp.Diff(mod, string(got)); diff != "" {
						t.Errorf("fs.ReadFile(ContentDir(%q), %q) mismatch [-want +got]:\n%s", modulePath, "go.mod", diff)
					}
				})

				t.Run("search", func(t *testing.T) {
					tests := []struct {
						query string
						want  []string
					}{
						{"log", []string{"barlog", "foolog"}},
						{"barlog", []string{"barlog"}},
						{"xxxxxx", nil},
					}

					for _, test := range tests {
						results, err := g.Search(ctx, test.query, 10)
						if err != nil {
							t.Fatal(err)
						}
						var got []string
						for _, r := range results {
							got = append(got, r.Name)
						}
						if diff := cmp.Diff(test.want, got); diff != "" {
							t.Errorf("Search(%s) mismatch [-want +got]:\n%s", test.query, diff)
						}
					}
				})
			}
		})
	}
}

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

	tempDir, _ := testhelper.WriteTxtarToTempDir(t, multiModule)

	// Sleep before fetching the initial info, so that the written mtime will be
	// considered reliable enough for caching by the getter.
	time.Sleep(3 * time.Second)

	g, err := NewGoPackagesModuleGetter(ctx, tempDir, "all")
	if err != nil {
		t.Fatal(err)
	}

	const fooPath = "foo.com/foo"
	foo1, err := g.Info(ctx, fooPath, "")
	if err != nil {
		t.Fatal(err)
	}
	foo2, err := g.Info(ctx, fooPath, "")
	if err != nil {
		t.Fatal(err)
	}
	if !cmp.Equal(foo1, foo2) {
		t.Errorf("Info(%q) returned inconsistent results: %v != %v", fooPath, foo1, foo2)
	}

	const barPath = "bar.com/bar"
	bar1, err := g.Info(ctx, barPath, "")
	if err != nil {
		t.Fatal(err)
	}
	bar2, err := g.Info(ctx, barPath, "")
	if err != nil {
		t.Fatal(err)
	}
	if !cmp.Equal(bar1, bar2) {
		t.Errorf("Info(%q) returned inconsistent results: %v != %v", barPath, bar1, bar2)
	}

	fpath := filepath.Join(tempDir, "foo", "foolog", "f.go")
	newContent := []byte("package foolog; const Log = 3")
	if err := os.WriteFile(fpath, newContent, 0600); err != nil {
		t.Fatal(err)
	}
	foo3, err := g.Info(ctx, fooPath, "")
	if err != nil {
		t.Fatal(err)
	}
	if cmp.Equal(foo1, foo3) {
		t.Errorf("Info(%q) results unexpectedly match: %v == %v", fooPath, foo1, foo3)
	}
	bar3, err := g.Info(ctx, barPath, "")
	if err != nil {
		t.Fatal(err)
	}
	if !cmp.Equal(bar1, bar2) {
		t.Errorf("Info(%q) returned inconsistent results: %v != %v", barPath, bar1, bar3)
	}
}

func TestEscapedPath(t *testing.T) {
	for _, test := range []struct {
		path, version, suffix string
		want                  string
	}{
		{
			"m.com", "v1", "info",
			"dir/cache/download/m.com/@v/v1.info",
		},
		{
			"github.com/aBc", "v2.3.4", "zip",
			"dir/cache/download/github.com/a!bc/@v/v2.3.4.zip",
		},
	} {
		g, err := NewModCacheGetter("dir")
		if err != nil {
			t.Fatal(err)
		}
		got, err := g.escapedPath(test.path, test.version, test.suffix)
		if err != nil {
			t.Fatal(err)
		}
		want, err := filepath.Abs(test.want)
		if err != nil {
			t.Fatal(err)
		}
		if got != want {
			t.Errorf("%s, %s, %s: got %q, want %q", test.path, test.version, test.suffix, got, want)
		}
	}
}

func TestFSProxyGetter(t *testing.T) {
	ctx := context.Background()
	const (
		modulePath = "github.com/jackc/pgio"
		vers       = "v1.0.0"
		goMod      = "module github.com/jackc/pgio\n\ngo 1.12\n"
	)
	ts, err := time.Parse(time.RFC3339, "2019-03-30T17:04:38Z")
	if err != nil {
		t.Fatal(err)
	}
	g, err := NewModCacheGetter("testdata/modcache")
	if err != nil {
		t.Fatal(err)
	}
	t.Run("info", func(t *testing.T) {
		got, err := g.Info(ctx, modulePath, vers)
		if err != nil {
			t.Fatal(err)
		}
		want := &proxy.VersionInfo{Version: vers, Time: ts}
		if !cmp.Equal(got, want) {
			t.Errorf("got %+v, want %+v", got, want)
		}

		// Asking for latest should give the same version.
		got, err = g.Info(ctx, modulePath, version.Latest)
		if err != nil {
			t.Fatal(err)
		}
		if !cmp.Equal(got, want) {
			t.Errorf("got %+v, want %+v", got, want)
		}

		if _, err := g.Info(ctx, "nozip.com", vers); !errors.Is(err, derrors.NotFound) {
			t.Errorf("got %v, want NotFound", err)
		}
	})
	t.Run("mod", func(t *testing.T) {
		got, err := g.Mod(ctx, modulePath, vers)
		if err != nil {
			t.Fatal(err)
		}
		want := []byte(goMod)
		if !cmp.Equal(got, want) {
			t.Errorf("got %q, want %q", got, want)
		}

		if _, err := g.Mod(ctx, "nozip.com", vers); !errors.Is(err, derrors.NotFound) {
			t.Errorf("got %v, want NotFound", err)
		}
	})
	t.Run("contentdir", func(t *testing.T) {
		fsys, err := g.ContentDir(ctx, modulePath, vers)
		if err != nil {
			t.Fatal(err)
		}
		// Just check that the go.mod file is there and has the right contents.
		f, err := fsys.Open("go.mod")
		if err != nil {
			t.Fatal(err)
		}
		defer f.Close()
		got, err := io.ReadAll(f)
		if err != nil {
			t.Fatal(err)
		}
		want := []byte(goMod)
		if !cmp.Equal(got, want) {
			t.Errorf("got %q, want %q", got, want)
		}

		if _, err := g.ContentDir(ctx, "nozip.com", vers); !errors.Is(err, derrors.NotFound) {
			t.Errorf("got %v, want NotFound", err)
		}
	})
}
