package gcs_baseliner

import (
	"testing"

	"github.com/stretchr/testify/mock"
	assert "github.com/stretchr/testify/require"
	"go.skia.org/infra/go/deepequal"
	"go.skia.org/infra/go/testutils/unittest"
	"go.skia.org/infra/golden/go/baseline"
	"go.skia.org/infra/golden/go/mocks"
	"go.skia.org/infra/golden/go/storage"
	three_devices "go.skia.org/infra/golden/go/testutils/data_three_devices"
	"go.skia.org/infra/golden/go/types"
)

// Test that the baseliner passes on the request to the storage.GCSClient
// for a baseline it hasn't seen before
func TestFetchBaselineSunnyDay(t *testing.T) {
	unittest.SmallTest(t)

	testCommitHash := "abcd12345"

	mgs := makeMockGCSStorage()
	defer mgs.AssertExpectations(t)

	mgs.On("ReadBaseline", testCommitHash, types.MasterBranch).Return(three_devices.MakeTestBaseline(), nil).Once()

	baseliner, err := New(mgs, nil, nil, nil)
	assert.NoError(t, err)

	b, err := baseliner.FetchBaseline(testCommitHash, types.MasterBranch, false)
	assert.NoError(t, err)

	deepequal.AssertDeepEqual(t, three_devices.MakeTestBaseline(), b)
}

// Test that the baseliner behaves differently when requesting a baseline
// for a given tryjob.
func TestFetchBaselineIssueSunnyDay(t *testing.T) {
	unittest.SmallTest(t)

	testCommitHash := "abcd12345"
	testIssueID := int64(1234)

	// These are valid, but arbitrary md5 hashes
	IotaNewDigest := types.Digest("1115fba4ce5b4cb9ffd595beb63e7389")
	KappaNewDigest := types.Digest("222d894f5b680a9f7bd74c8004b7d88d")
	LambdaNewDigest := types.Digest("3333fe3127b984e4ff39f4885ddb0d98")

	additionalTriages := &baseline.Baseline{
		Expectations: types.Expectations{
			"brand-new-test": map[types.Digest]types.Label{
				IotaNewDigest:  types.POSITIVE,
				KappaNewDigest: types.NEGATIVE,
			},
			three_devices.BetaTest: map[types.Digest]types.Label{
				LambdaNewDigest: types.POSITIVE,
				// Change these two pre-existing digests
				three_devices.BetaGood1Digest:      types.NEGATIVE,
				three_devices.BetaUntriaged1Digest: types.POSITIVE,
			},
		},
		Issue: testIssueID,

		StartCommit: nil, // This can all be blank, and in some real-world data, is blank
		EndCommit:   nil,
		Filled:      0,
		Total:       0,
	}

	mgs := makeMockGCSStorage()
	defer mgs.AssertExpectations(t)

	// mock the master baseline
	mgs.On("ReadBaseline", testCommitHash, types.MasterBranch).Return(three_devices.MakeTestBaseline(), nil).Once()
	// mock the expectations that a user would have applied to their CL (that
	// are not live on master yet).
	mgs.On("ReadBaseline", "", testIssueID).Return(additionalTriages, nil).Once()

	baseliner, err := New(mgs, nil, nil, nil)
	assert.NoError(t, err)

	b, err := baseliner.FetchBaseline(testCommitHash, testIssueID, false)
	assert.NoError(t, err)

	assert.Equal(t, testIssueID, b.Issue)
	// The expectation should be the master baseline merged in with the additionalTriages
	// with additionalTriages overwriting existing expectations, if applicable.
	assert.Equal(t, types.Expectations{
		"brand-new-test": map[types.Digest]types.Label{
			IotaNewDigest:  types.POSITIVE,
			KappaNewDigest: types.NEGATIVE,
		},
		// AlphaTest should be unchanged from the master baseline.
		three_devices.AlphaTest: map[types.Digest]types.Label{
			three_devices.AlphaBad1Digest:       types.NEGATIVE,
			three_devices.AlphaGood1Digest:      types.POSITIVE,
			three_devices.AlphaUntriaged1Digest: types.UNTRIAGED,
		},
		three_devices.BetaTest: map[types.Digest]types.Label{
			LambdaNewDigest: types.POSITIVE,
			// Note that the state caused by this set of expectations overwrites what
			// was on the master branch
			three_devices.BetaGood1Digest:      types.NEGATIVE,
			three_devices.BetaUntriaged1Digest: types.POSITIVE,
		},
	}, b.Expectations)

	// Ensure that reading the issue branch does not impact the master branch
	b, err = baseliner.FetchBaseline(testCommitHash, types.MasterBranch, false)
	assert.NoError(t, err)
	assert.Equal(t, three_devices.MakeTestBaseline(), b)
}

func TestFetchBaselineCachingSunnyDay(t *testing.T) {
	unittest.SmallTest(t)

	testCommitHash := "abcd12345"

	mgs := makeMockGCSStorage()
	defer mgs.AssertExpectations(t)

	// ReadBaseline should only be called once despite multiple requests below
	mgs.On("ReadBaseline", testCommitHash, types.MasterBranch).Return(three_devices.MakeTestBaseline(), nil).Once()

	baseliner, err := New(mgs, nil, nil, nil)
	assert.NoError(t, err)

	for i := 0; i < 10; i++ {
		b, err := baseliner.FetchBaseline(testCommitHash, types.MasterBranch, false)
		assert.NoError(t, err)
		assert.NotNil(t, b)
		deepequal.AssertDeepEqual(t, three_devices.MakeTestBaseline(), b)
	}
}

// TODO(kjlubick): TestFetchBaseline which returns nil (difficult because it shells out to
// PushMasterBaseline)

// TestPushMasterBaselineSunnyDay verifies that the baseliner pulls in the latest tile
// (which has the traces and known images) and combines it with the triage status from
// ExpectationsStorage to create a baseline per commit.
func TestPushMasterBaselineSunnyDay(t *testing.T) {
	unittest.SmallTest(t)

	mgs := makeMockGCSStorage()
	mcs := &mocks.TileInfo{}
	mes := &mocks.ExpectationsStore{}

	defer mgs.AssertExpectations(t)
	defer mcs.AssertExpectations(t)
	defer mes.AssertExpectations(t)

	mcs.On("AllCommits").Return(three_devices.MakeTestCommits())
	mcs.On("DataCommits").Return(three_devices.MakeTestCommits())
	mcs.On("GetTile", types.ExcludeIgnoredTraces).Return(three_devices.MakeTestTile())

	mes.On("Get").Return(three_devices.MakeTestExpectations(), nil)

	mgs.On("WriteBaseline", mock.AnythingOfType("*baseline.Baseline")).Run(func(args mock.Arguments) {
		b := args.Get(0).(*baseline.Baseline)
		assert.NotNil(t, b)
		assert.NotNil(t, b.StartCommit)
		// These commits are per-commit baselines, thus the start and end are the same
		deepequal.AssertDeepEqual(t, *b.StartCommit, *b.EndCommit)

		assert.Equal(t, 6, b.Total)

		// These per-commit baselines keep track of only the positive images we have seen,
		// so make sure we see betaGood1Digest for all 3 and alphaGood1Digest show up in the
		// third commit
		switch b.StartCommit.Hash {
		default:
			assert.Fail(t, "Bad hash", b.StartCommit.Hash)
		case three_devices.FirstCommitHash:
			assert.Equal(t, 1, b.Filled)
			assertLabel(t, b, three_devices.BetaTest, three_devices.BetaGood1Digest, types.POSITIVE)
		case three_devices.SecondCommitHash:
			assert.Equal(t, 1, b.Filled)
			assertLabel(t, b, three_devices.BetaTest, three_devices.BetaGood1Digest, types.POSITIVE)
		case three_devices.ThirdCommitHash:
			assert.Equal(t, 2, b.Filled)
			assertLabel(t, b, three_devices.AlphaTest, three_devices.AlphaGood1Digest, types.POSITIVE)
			assertLabel(t, b, three_devices.BetaTest, three_devices.BetaGood1Digest, types.POSITIVE)
		}
	}).Return("gs://test-bucket/baselines/foo-baseline.json", nil).Times(3) // once per commit

	baseliner, err := New(mgs, mes, nil, nil)
	assert.NoError(t, err)

	b, err := baseliner.PushMasterBaselines(mcs, "")
	assert.NoError(t, err)
	assert.Nil(t, b) // baseline should be nil because commit is ""
}

func makeMockGCSStorage() *mocks.GCSClient {
	mgs := mocks.GCSClient{}
	mgs.On("Options").Return(storage.GCSClientOptions{
		HashesGSPath:   "gs://test-bucket/hashes",
		BaselineGSPath: "gs://test-bucket/baselines/",
	}).Maybe()
	return &mgs
}

func assertLabel(t *testing.T, b *baseline.Baseline, testName types.TestName, hash types.Digest, label types.Label) {
	test, ok := b.Expectations[testName]
	if !ok {
		assert.Failf(t, "assertLabel", "Could not find test %s in baseline %#v", testName, b)
	}

	lab, ok := test[hash]
	if !ok {
		assert.Failf(t, "assertLabel", "Could not find hash %s in test %#v (name %s) (baseline %#v)", hash, test, testName, b)
	}
	assert.Equal(t, label, lab)
}
