// Copyright 2023 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 vulndbreqs

import (
	"context"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"cloud.google.com/go/civil"
	"cloud.google.com/go/storage"
	"github.com/google/go-cmp/cmp"
	"github.com/google/go-cmp/cmp/cmpopts"
	"golang.org/x/exp/maps"
	"golang.org/x/exp/slices"
	test "golang.org/x/pkgsite-metrics/internal/testing"
)

func TestComputeFromLogs(t *testing.T) {
	test.NeedsIntegrationEnv(t)

	projID := os.Getenv("GO_ECOSYSTEM_VULNDB_BUCKET_PROJECT")
	if projID == "" {
		t.Skip("GO_ECOSYSTEM_VULNDB_BUCKET_PROJECT not defined")
	}
	// Compute yesterday's counts, up to 10 log entries.
	// Assume there are more than 10 requests a day.
	yesterday := civil.DateOf(time.Now()).AddDays(-1)
	const n = 10
	igot, err := computeFromLogs(context.Background(), projID, yesterday, testHMACKey, n)
	if err != nil {
		t.Fatal(err)
	}
	got := sumRequestCounts(igot)
	want := []*RequestCount{{
		Date:  yesterday,
		Count: 10,
	}}
	if diff := cmp.Diff(want, got); diff != "" {
		t.Errorf("mismatch (-want, +got):\n%s", diff)
	}
}

func TestComputeFromStorage(t *testing.T) {
	test.NeedsIntegrationEnv(t)

	// Compute one day's counts, reading only 1 file.
	// The file is always the same.
	got, err := computeFromStorage(context.Background(), testDate, testHMACKey, 1)
	if err != nil {
		t.Fatal(err)
	}
	// The returned slice comes from a map, so sort for determinism.
	slices.SortFunc(got, func(r1, r2 *IPRequestCount) bool {
		return r1.Count < r2.Count
	})
	want := []*IPRequestCount{
		{Date: testDate, Count: 30},
		{Date: testDate, Count: 33},
		{Date: testDate, Count: 112},
	}
	if diff := cmp.Diff(got, want, cmpopts.IgnoreFields(IPRequestCount{}, "IP")); diff != "" {
		t.Errorf("mismatch (-want, +got)\n%s", diff)
	}
}

var (
	testHMACKey = []byte("this-is-a-fake-hmac-key")

	testDate = civil.Date{Year: 2023, Month: 5, Day: 30}

	// These reflect the contents of testdata/logfile.json,
	// which is also stored in the "test" directory of the
	// vulndb logs bucket.
	testFileDates = map[civil.Date]int{testDate: 13}
	testFileIPs   = map[string]int{
		obfuscate("1.2.3.4", testHMACKey):    3,
		obfuscate("5.6.7.8", testHMACKey):    2,
		obfuscate("9.10.11.12", testHMACKey): 8,
	}
)

func TestReadJSONLogEntries(t *testing.T) {
	f, err := os.Open(filepath.Join("testdata", "logfile.json"))
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	gotDates := map[civil.Date]int{}
	gotIPs := map[string]int{}
	err = readJSONLogEntries(f, testHMACKey, func(e *logEntry) error {
		gotDates[civil.DateOf(e.Timestamp)]++
		gotIPs[e.HTTPRequest.RemoteIP]++
		return nil
	})
	if err != nil {
		t.Fatal(err)
	}
	if !maps.Equal(gotDates, testFileDates) {
		t.Errorf("dates:\ngot  %v\nwant %v", gotDates, testFileDates)
	}
	if !maps.Equal(gotIPs, testFileIPs) {
		t.Errorf("IPs:\ngot  %v\nwant %v", gotIPs, testFileIPs)
	}
}

func TestCountFiles(t *testing.T) {
	test.NeedsIntegrationEnv(t)

	// Actual bucket containing logs data.
	bucketName := os.Getenv("GOOGLE_CLOUD_PROJECT") + bucketSuffix

	// Files manually copied to the bucket for testing.
	const testPrefix = "test"
	const wantPrefix = "test/2023/05/30/"

	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()
	bucket := client.Bucket(bucketName)

	t.Run("ObjectNamesForDate", func(t *testing.T) {
		const wantNFiles = 2
		got, err := objectNamesForDate(ctx, bucket, testPrefix, testDate)
		if err != nil {
			t.Fatal(err)
		}
		if g := len(got); g != wantNFiles {
			t.Errorf("got %d files, want %d", g, wantNFiles)
		}

		for _, g := range got {
			if !strings.HasPrefix(g, wantPrefix) || !strings.HasSuffix(g, ".json") {
				t.Errorf(`got %q, want "%sFILENAME.json"`, g, wantPrefix)
			}
		}
	})

	t.Run("CountLogsForObjects", func(t *testing.T) {
		// The two files with the testPrefix are both copies of testdata/logfile.json.
		objNames := []string{wantPrefix + "logfile1.json", wantPrefix + "logfile2.json"}
		gotDates, gotIPs, err := countLogsForObjects(ctx, bucket, objNames, testHMACKey)
		if err != nil {
			t.Fatal(err)
		}
		// There are two files, so data is doubled.
		wantDates := maps.Clone(testFileDates)
		for k, v := range wantDates {
			wantDates[k] = v * 2
		}
		wantIPs := maps.Clone(testFileIPs)
		for k, v := range wantIPs {
			wantIPs[k] = v * 2
		}
		if !maps.Equal(gotDates, wantDates) {
			t.Errorf("dates:\ngot  %v\nwant %v", gotDates, wantDates)
		}
		if !maps.Equal(gotIPs, wantIPs) {
			t.Errorf("IPs:\ngot  %v\nwant %v", gotIPs, wantIPs)
		}
	})
}
