package arrays

import (
	"reflect"
	"slices"
	"testing"
)

// go test -cover will show the test coverage for our package.

func TestSum(t *testing.T) {

	t.Run("sum collection of 5 of integers", func(t *testing.T) {
		numbers := []int{1, 2, 3, 4, 5}

		got := Sum(numbers)
		expected := 15

		// https://pkg.go.dev/fmt
		if got != expected {
			t.Errorf("got %d expected %d given, %v", got, expected, numbers)
		}
	})

	// go test -cover will show the test coverage for our package.

	// You can see that commenting out this "duplicate" function still retains 100%
	// test coverage, which is how we know it's redundant.

	// t.Run("sum a collection of any size", func(t *testing.T) {
	// 	numbers := []int{1, 2, 3}

	// 	got := Sum(numbers)
	// 	expected := 6

	// 	// https://pkg.go.dev/fmt
	// 	if got != expected {
	// 		t.Errorf("got %d expected %d given, %v", got, expected, numbers)
	// 	}
	// })

}

func TestSumAll(t *testing.T) {

	got := SumAll([]int{1, 2}, []int{0, 9})
	expected := []int{3, 9}

	// can't compare slices...slices can only be compared to nil
	// if got != expected {
	// 	t.Errorf("got %v expected %v given", got, expected)
	// }

	// https://pkg.go.dev/reflect#DeepEqual standard lib to the rescue

	// It's important to note that reflect.DeepEqual is not "type safe"
	// - the code will compile even if you did something a bit silly.
	// To see this in action, temporarily change the test to:

	// func TestSumAll(t *testing.T) {

	// 	got := SumAll([]int{1, 2}, []int{0, 9})
	// 	want := "bob"

	// 	if !reflect.DeepEqual(got, want) {
	// 		t.Errorf("got %v want %v", got, want)
	// 	}
	// }

	if !reflect.DeepEqual(got, expected) {
		t.Errorf("Using reflect.DeepEqual got %v expected %v given", got, expected)
	}

	// From Go 1.21, slices standard package is available, which has a
	// slices.Equal function to do a simple shallow compare on slices,
	// where you don't need to worry about the types like the above case.
	// Note that this function expects the elements to be comparable
	// So, it can't be applied to slices with non-comparable elements like 2D slices.

	if !slices.Equal(got, expected) {
		t.Errorf("Using slices.Equal got %v expected %v given", got, expected)
	}
}

// The tail of a collection is all items in the collection except the first one (the "head").
func TestSumAllTails(t *testing.T) {

	// Another example of helper function
	// By defining this function inside the test, it cannot be used by other functions in this package.
	checkSums := func(t testing.TB, got, want []int) {
		t.Helper()
		if !reflect.DeepEqual(got, want) {
			t.Errorf("got %v want %v", got, want)
		}
	}

	t.Run("test slices of same lenght", func(t *testing.T) {
		got := SumAllTails([]int{1, 2}, []int{0, 9})
		want := []int{2, 9}

		checkSums(t, got, want)
	})

	t.Run("test an empty slice and slice of different len", func(t *testing.T) {
		got := SumAllTails([]int{}, []int{0, 4, 5})
		want := []int{0, 9}

		checkSums(t, got, want)
	})
}
