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

import (
	"context"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"golang.org/x/pkgsite/internal/fetch"
	"golang.org/x/pkgsite/internal/frontend"
	"golang.org/x/pkgsite/internal/middleware"
	"golang.org/x/pkgsite/internal/postgres"
	"golang.org/x/pkgsite/internal/proxy"
	"golang.org/x/pkgsite/internal/source"
	"golang.org/x/pkgsite/internal/testing/htmlcheck"
	"golang.org/x/pkgsite/internal/testing/testhelper"
)

var (
	in      = htmlcheck.In
	hasText = htmlcheck.HasText
)

func TestModulePackageDirectoryResolution(t *testing.T) {
	// The shared test state sets up the following scenario to exercise the types
	// of problems discussed in b/143814014: a directory that becomes a package,
	// and then becomes a directory again. Specifically:
	//  + at v1.2.3, github.com/golang/found/dir is a directory (containing dir/pkg)
	//  + at v1.2.4, github.com/golang/found/dir is a package
	//  + at v1.2.5, github.com/golang/found/dir is again just a directory
	versions := []*proxy.TestModule{
		{
			ModulePath: "github.com/golang/found",
			Version:    "v1.2.3",
			Files: map[string]string{
				"go.mod":         "module github.com/golang/found",
				"found.go":       "package found\nconst Value = 123",
				"dir/pkg/pkg.go": "package pkg\nconst Value = 321",
				"LICENSE":        testhelper.MITLicense,
			},
		},
		{
			ModulePath: "github.com/golang/found",
			Version:    "v1.2.4",
			Files: map[string]string{
				"go.mod":         "module github.com/golang/found",
				"found.go":       "package found\nconst Value = 124",
				"dir/pkg/pkg.go": "package pkg\nconst Value = 421",
				"dir/dir.go":     "package dir\nconst Value = \"I'm a package!\"",
				"LICENSE":        testhelper.MITLicense,
			},
		},
		{
			ModulePath: "github.com/golang/found",
			Version:    "v1.2.5",
			Files: map[string]string{
				"go.mod":         "module github.com/golang/found",
				"found.go":       "package found\nconst Value = 125",
				"dir/pkg/pkg.go": "package pkg\nconst Value = 521",
				"LICENSE":        testhelper.MITLicense,
			},
		},
	}

	tests := []struct {
		// Test description.
		desc string
		// URL Path (relative to the test server) to check
		urlPath string
		// The expected HTTP status code.
		wantCode int
		// If non-nil, used to verify the resulting page.
		want htmlcheck.Checker
	}{
		{
			desc:     "missing module",
			urlPath:  "/mod/github.com/golang/missing",
			wantCode: http.StatusNotFound,
		},
		{
			desc:     "latest module",
			urlPath:  "/mod/github.com/golang/found",
			wantCode: http.StatusOK,
			want: in("",
				in(".DetailsHeader", hasText("v1.2.5")),
				in(".DetailsHeader-badge", in(".DetailsHeader-badge--latest"))),
		},
		{
			desc:     "versioned module",
			urlPath:  "/mod/github.com/golang/found@v1.2.3",
			wantCode: http.StatusOK,
			want:     in(".DetailsHeader", hasText("v1.2.3")),
		},
		{
			desc:     "non-existent version",
			urlPath:  "/mod/github.com/golang/found@v1.1.3",
			wantCode: http.StatusNotFound,
			want: in(".Content",
				hasText("not available"),
				hasText("other versions of this module")),
		},
		{
			desc:     "latest package",
			urlPath:  "/github.com/golang/found/dir/pkg",
			wantCode: http.StatusOK,
			want: in("",
				in(".DetailsHeader", hasText("v1.2.5")),
				in(".DetailsContent", hasText("521")),
				in(".DetailsHeader-badge", in(".DetailsHeader-badge--latest"))),
		},
		{
			desc:     "earlier package",
			urlPath:  "/github.com/golang/found@v1.2.3/dir/pkg",
			wantCode: http.StatusOK,
			want: in("",
				in(".DetailsHeader", hasText("v1.2.3")),
				in(".DetailsContent", hasText("321"))),
		},
		{
			desc:     "dir is initially a directory",
			urlPath:  "/github.com/golang/found@v1.2.3/dir",
			wantCode: http.StatusOK,
			want:     in(".Directories", hasText("pkg")),
		},
		{
			desc:     "dir becomes a package",
			urlPath:  "/github.com/golang/found@v1.2.4/dir",
			wantCode: http.StatusOK,
			want: in("",
				in(".DetailsHeader", hasText("v1.2.4")),
				in(".DetailsContent", hasText("I'm a package"))),
		},
		{
			desc:     "dir becomes a directory again",
			urlPath:  "/github.com/golang/found@v1.2.5/dir",
			wantCode: http.StatusOK,
			want: in("",
				in(".Directories", hasText("pkg")),
				in(".DetailsHeader-badge", in(".DetailsHeader-badge--unknown"))),
		},
		{
			desc:     "latest package for /dir",
			urlPath:  "/github.com/golang/found/dir",
			wantCode: http.StatusOK,
			want: in("",
				in(".DetailsHeader", hasText("v1.2.4")),
				in(".DetailsContent", hasText("I'm a package"))),
		},
	}
	s, err := frontend.NewServer(frontend.ServerConfig{
		DataSource:           testDB,
		TaskIDChangeInterval: 10 * time.Minute,
		StaticPath:           "../../../content/static",
		ThirdPartyPath:       "../../../third_party",
	})
	if err != nil {
		t.Fatal(err)
	}
	mux := http.NewServeMux()
	s.Install(mux.Handle, nil)
	handler := middleware.LatestVersion(s.LatestVersion)(mux)
	ts := httptest.NewServer(handler)
	processVersions(context.Background(), t, versions)
	defer postgres.ResetTestDB(testDB, t)

	for _, test := range tests {
		t.Run(test.desc, func(t *testing.T) {
			resp, err := http.Get(ts.URL + test.urlPath)
			if err != nil {
				t.Fatal(err)
			}
			defer resp.Body.Close()
			if resp.StatusCode != test.wantCode {
				t.Errorf("GET %s returned status %d, want %d", test.urlPath, resp.StatusCode, test.wantCode)
			}
			if test.want != nil {
				if err := htmlcheck.Run(resp.Body, test.want); err != nil {
					t.Error(err)
				}
			}
		})
	}

}

func processVersions(ctx context.Context, t *testing.T, testModules []*proxy.TestModule) {
	t.Helper()
	proxyClient, teardown := proxy.SetupTestProxy(t, testModules)
	defer teardown()
	sourceClient := source.NewClient(1 * time.Second)

	for _, tm := range testModules {
		res := fetch.FetchModule(ctx, tm.ModulePath, tm.Version, proxyClient, sourceClient)
		if res.Error != nil {
			t.Fatal(res.Error)
		}
		if err := testDB.InsertModule(ctx, res.Module); err != nil {
			t.Fatal(err)
		}
	}
}
