package events

import (
	"fmt"
	"github.com/olivere/elastic/v7"
	log "github.com/sirupsen/logrus"
	"iwarma.ru/console/correlator/es"
	"iwarma.ru/console/correlator/util"
	"reflect"
	"testing"
)

func TestParseNormalizedEvents(t *testing.T) {
	util.SetupTest(t)
	defer util.TearDownTest(t)

	index := "my_test_index"

	client, err := es.NewElastic()
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	err = ClearIndex(client, index)
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	// Add documents
	goodCount := 10
	err = FillNormalizedEvents(index, goodCount, client)
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	query := elastic.NewMatchAllQuery()

	raw, errs1 := client.Query(index, query)
	events, errs2 := ParseEvents(raw, errs1, 1)

	// Now let's count
	eventCount := 0
	for range events {
		eventCount++
	}

	errCount := 0
	for err = range errs2 {
		if err != nil {
			log.Errorf("Got error: %v", err)
			errCount++
		}
	}

	if eventCount != goodCount {
		t.Errorf("Bad event count. Expect %v, got %v", goodCount, eventCount)
	}

	if errCount > 0 {
		t.Error("Got some errors")
	}

}

func TestParseAggregatedEvents(t *testing.T) {
	util.SetupTest(t)
	defer util.TearDownTest(t)

	index := "my_test_index"

	client, err := es.NewElastic()
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	err = ClearIndex(client, index)
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	// Add documents
	goodCount := 10
	err = FillAggregatedEvents(index, goodCount, client)
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	query := elastic.NewMatchAllQuery()

	raw, errs1 := client.Query(index, query)
	events, errs2 := ParseEvents(raw, errs1, 1)

	// Now let's count
	eventCount := 0
	for range events {
		eventCount++
	}

	errCount := 0
	for err = range errs2 {
		if err != nil {
			log.Errorf("Got error: %v", err)
			errCount++
		}
	}

	if eventCount != goodCount {
		t.Errorf("Bad event count. Expect %v, got %v", goodCount, eventCount)
	}

	if errCount > 0 {
		t.Error("Got some errors")
	}

}

func TestParseNormalizedEventsMassive(t *testing.T) {
	util.SetupTest(t)
	defer util.TearDownTest(t)

	index := "my_test_index"

	client, err := es.NewElastic()
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	err = ClearIndex(client, index)
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	// Add documents
	goodCount := 50000
	err = FillNormalizedEvents(index, goodCount, client)
	if err != nil {
		t.Errorf("%v", err)
		return
	}

	query := elastic.NewMatchAllQuery()

	raw, errs1 := client.Query(index, query)
	events, errs2 := ParseEvents(raw, errs1, 20)

	// Now let's count
	eventCount := 0
	for range events {
		eventCount++
	}

	errCount := 0
	for err = range errs2 {
		if err != nil {
			log.Errorf("Got error: %v", err)
			errCount++
		}
	}

	if eventCount != goodCount {
		t.Errorf("Bad event count. Expect %v, got %v", goodCount, eventCount)
	}

	if errCount > 0 {
		t.Error("Got some errors")
	}

}

func TestAddTag(t *testing.T) {
	events, err := PrepareEvents(2)
	if err != nil {
		t.Errorf("%v", err)
	}
	for event := range events {
		// In new events tags is nil -> add tags will increment tags to nill
		tags := event.AddTag("1")
		exampleTags := []string{"1"}
		if !reflect.DeepEqual(tags, exampleTags) {
			t.Errorf("Bad event tags! Expect %v , have %v", exampleTags, tags)
		}
		tags = event.AddTag("2")
		exampleDoubleTags := []string{"1", "2"}
		if !reflect.DeepEqual(tags, exampleDoubleTags) {
			t.Errorf("Bad event tags! Expect %v , have %v", exampleDoubleTags, tags)
		}

	}

}

func TestGetValue(t *testing.T) {
	events, err := PrepareEvents(1)
	if err != nil {
		t.Errorf("%v", err)
	}
	for event := range events {
		typeValue, ok := event.GetValue("type").(string)
		if !ok {
			t.Errorf("Can`t get event value")
		}
		severityValue, ok := event.GetValue("event_severity").(float64)
		if !ok {
			t.Errorf("Can`t get event value")
		}
		if typeValue != "test" {
			t.Errorf("Bad event value! Expect %v , have %v", "test", typeValue)
		}
		if severityValue != 0 {
			t.Errorf("Bad event value! Expect %v , have %v", 0, severityValue)
		}

	}

}

func TestGetString(t *testing.T) {
	events, err := PrepareEvents(1)
	if err != nil {
		t.Errorf("%v", err)
	}
	for event := range events {
		hostValue := event.GetString("source_host")
		if hostValue != "localhost" {
			t.Errorf("Bad event value! Expect %v , have %v", "localhost", hostValue)
		}
	}

}

func TestGetInt(t *testing.T) {
	events, err := PrepareEvents(1)
	if err != nil {
		t.Errorf("%v", err)
	}
	for event := range events {
		portValue := event.GetInt("destination_port")
		if portValue != 0 {
			t.Errorf("Bad event value! Expect %v , have %v", 0, portValue)
		}
	}

}

func PrepareEvents(eventsNeed int) (chan *Event, error) {
	util.PrepareElastic()
	index := "test-aggregated"
	client, err := es.NewElastic()
	if err != nil {

		return nil, err
	}
	err = ClearIndex(client, GetAggregatedIndexName())
	if err != nil {
		return nil, err
	}

	err = FillAggregatedEvents(GetAggregatedIndexName(), 1, client)
	if err != nil {
		return nil, err
	}
	query := elastic.NewMatchAllQuery()

	raw, errs1 := client.Query(index, query)
	events, error2 := ParseEvents(raw, errs1, eventsNeed)

	errorsCount := 0
	for err = range error2 {
		if err != nil {
			fmt.Printf("Got error: %v", err)
			errorsCount += 1
		}
	}
	if errorsCount != 0 {
		return nil, fmt.Errorf("Can`t get events from elastic -> %v ", error2)
	} else {
		return events, nil
	}

}
