// 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"
	"os"
	"testing"
	"time"

	"github.com/go-redis/redis/v8"
	"github.com/google/safehtml/template"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/config"
	"golang.org/x/pkgsite/internal/experiment"
	"golang.org/x/pkgsite/internal/fetch"
	"golang.org/x/pkgsite/internal/frontend"
	"golang.org/x/pkgsite/internal/frontend/fetchserver"
	"golang.org/x/pkgsite/internal/middleware"
	"golang.org/x/pkgsite/internal/proxy"
	"golang.org/x/pkgsite/internal/proxy/proxytest"
	"golang.org/x/pkgsite/internal/queue"
	"golang.org/x/pkgsite/internal/queue/inmemqueue"
	"golang.org/x/pkgsite/internal/source"
	"golang.org/x/pkgsite/internal/testing/htmlcheck"
)

// TODO(https://github.com/golang/go/issues/40096): factor out this code reduce
// duplication
func setupFrontend(ctx context.Context, t *testing.T, q queue.Queue, rc *redis.Client) *httptest.Server {
	t.Helper()
	const staticDir = "../../../static"
	fs := &fetchserver.FetchServer{
		Queue:                q,
		TaskIDChangeInterval: 10 * time.Minute,
	}
	s, err := frontend.NewServer(frontend.ServerConfig{
		FetchServer:      fs,
		DataSourceGetter: func(context.Context) internal.DataSource { return testDB },
		TemplateFS:       template.TrustedFSFromTrustedSource(template.TrustedSourceFromConstant(staticDir)),
		StaticFS:         os.DirFS(staticDir),
		ThirdPartyFS:     os.DirFS("../../../third_party"),
		Queue:            q,
		Config:           &config.Config{ServeStats: true},
	})
	if err != nil {
		t.Fatal(err)
	}
	mux := http.NewServeMux()
	var cacher frontend.Cacher
	if rc != nil {
		cacher = middleware.NewCacher(rc)
	}
	s.Install(mux.Handle, cacher, nil)

	// Get experiments from the context. Fully roll them out.
	expNames := experiment.FromContext(ctx).Active()
	var exps []*internal.Experiment
	for _, n := range expNames {
		exps = append(exps, &internal.Experiment{
			Name:    n,
			Rollout: 100,
		})
	}
	getter := func(context.Context) ([]*internal.Experiment, error) {
		return exps, nil
	}

	experimenter, err := middleware.NewExperimenter(ctx, 1*time.Minute, getter, nil)
	if err != nil {
		t.Fatal(err)
	}
	enableCSP := true
	mw := middleware.Chain(
		middleware.AcceptRequests(http.MethodGet, http.MethodPost),
		middleware.SecureHeaders(enableCSP),
		middleware.Experiment(experimenter),
	)
	return httptest.NewServer(mw(mux))
}

// TODO(https://github.com/golang/go/issues/40098): factor out this code reduce
// duplication
func setupQueue(ctx context.Context, t *testing.T, proxyModules []*proxytest.Module, experimentNames ...string) (queue.Queue, func()) {
	cctx, cancel := context.WithCancel(ctx)
	proxyClient, teardown := proxytest.SetupTestClient(t, proxyModules)
	sourceClient := source.NewClient(http.DefaultClient)
	q := inmemqueue.New(cctx, 1, experimentNames,
		func(ctx context.Context, mpath, version string) (_ int, err error) {
			return fetchserver.FetchAndUpdateState(ctx, mpath, version, proxyClient, sourceClient, testDB)
		})
	return q, func() {
		cancel()
		teardown()
	}
}

func processVersions(ctx context.Context, t *testing.T, testModules []*proxytest.Module) {
	t.Helper()
	proxyClient, teardown := proxytest.SetupTestClient(t, testModules)
	defer teardown()

	for _, tm := range testModules {
		fetchAndInsertModule(ctx, t, tm, proxyClient)
	}
}

func fetchAndInsertModule(ctx context.Context, t *testing.T, tm *proxytest.Module, proxyClient *proxy.Client) {
	sourceClient := source.NewClient(http.DefaultClient)
	res := fetch.FetchModule(ctx, tm.ModulePath, tm.Version, fetch.NewProxyModuleGetter(proxyClient, sourceClient))
	if res.Error != nil {
		t.Fatal(res.Error)
	}
	// Populate the LatestVersion fields from the the latest version in the
	// proxytest.Module, computed in [proxytest.LoadTestModules].
	res.Module.LatestVersion = tm.LatestVersion
	for _, u := range res.Module.Units {
		u.LatestVersion = tm.LatestVersion
	}
	testDB.MustInsertModule(t, res.Module)
}

func validateResponse(t *testing.T, method, testURL string, wantCode int, wantHTML htmlcheck.Checker) {
	t.Helper()

	var (
		resp *http.Response
		err  error
	)
	if method == http.MethodPost {
		resp, err = http.Post(testURL, "text/plain", nil)
	} else {
		resp, err = http.Get(testURL)
	}
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != wantCode {
		t.Fatalf("%q request to %q returned status %d, want %d", method, testURL, resp.StatusCode, wantCode)
	}

	if wantHTML != nil {
		if err := htmlcheck.Run(resp.Body, wantHTML); err != nil {
			t.Fatal(err)
		}
	}
}
