package helpers_test

import "seekia/internal/helpers"

import "testing"

import "slices"


func TestTimeFunctions(t *testing.T){

	minuteUnix := int64(60)
	hourUnix := int64(3600)
	dayUnix := int64(86400)
	weekUnix := int64(604800)
	monthUnix := int64(2629743)
	yearUnix := int64(31556926)

	durationTranslated, err := helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(hourUnix, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Hour") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(hourUnix + minuteUnix*2, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Hour and 2 Minutes") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(dayUnix + minuteUnix*2, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Day") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(weekUnix + dayUnix*2, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Week and 2 Days") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(monthUnix + dayUnix*2, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Month and 2 Days") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(monthUnix + weekUnix, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Month and 1 Week") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(monthUnix + weekUnix*2, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Month and 2 Weeks") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(yearUnix + weekUnix*2, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "1 Year and 2 Weeks") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

	durationTranslated, err = helpers.ConvertUnixTimeDurationToUnitsTimeTranslated(10 * yearUnix + weekUnix*2, true)
	if (err != nil) {
		t.Fatal("Failed to get duration units time translated: " + err.Error())
	}

	if (durationTranslated != "10 Years") {
		t.Fatal("Invalid units time translated: " + durationTranslated)
	}

}


func TestIntToStringWithCommas(t *testing.T){
	
	num := 1

	result := helpers.ConvertIntToStringWithCommas(num)
	if (result != "1"){
		t.Fatal("Int to string with commas conversion failed")
	}

	num = 12

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "12"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 123

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "123"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 1234

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "1,234"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 12345

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "12,345"){
		
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 123456

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "123,456"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 1234567

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "1,234,567"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 12345678

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "12,345,678"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 123456789

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "123,456,789"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 1234567891

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "1,234,567,891"){
		t.Fatal("Int to string with commas conversion failed.")
	}

	num = 12345678912

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "12,345,678,912"){
		t.Fatal("Int to string with commas conversion failed.")
	}
	
	num = 123456789123

	result = helpers.ConvertIntToStringWithCommas(num)
	if (result != "123,456,789,123"){
		t.Fatal("Int to string with commas conversion failed.")
	}
}

func TestRandomNumberFunctions(t *testing.T){

	min := 1
	max := 100

	for i:=0; i < 100; i++{
		
		randomNumber := helpers.GetRandomIntWithinRange(min, max)
		if (randomNumber < min || randomNumber > max){
			t.Fatal("Failed to get random number between two numbers.")
		}
	}

	min = -10
	max = -5

	for i:=0; i < 100; i++{
		
		randomNumber := helpers.GetRandomIntWithinRange(min, max)
		if (randomNumber < min || randomNumber > max){
			t.Fatal("Failed to get random number between two numbers.")
		}
	}

	minInt64 := int64(0)
	maxInt64 := int64(100)

	for i:=0; i < 100; i++{
		
		randomNumber := helpers.GetRandomInt64WithinRange(minInt64, maxInt64)
		if (randomNumber < minInt64 || randomNumber > maxInt64){
			t.Fatal("Failed to get random number between two numbers.")
		}
	}

	minInt64 = int64(-30)
	maxInt64 = int64(50)

	for i:=0; i < 100; i++{
		
		randomNumber := helpers.GetRandomInt64WithinRange(minInt64, maxInt64)
		if (randomNumber < minInt64 || randomNumber > maxInt64){
			t.Fatal("Failed to get random number between two numbers.")
		}
	}
}

func TestGetRandomSliceElementFunction(t *testing.T){

	testListA := []string{"A"}

	result, err := helpers.GetRandomItemFromList(testListA)
	if (err != nil) {
		t.Fatal("Failed to get random item from string list: " + err.Error())
	}

	if (result != "A"){
		t.Fatal("Failed to get random item from string list- Invalid result: " + result)
	}

	testListB := []string{"A", "B", "C"}

	result, err = helpers.GetRandomItemFromList(testListB)
	if (err != nil) {
		t.Fatal("Failed to get random item from string list: " + err.Error())
	}

	isValid := slices.Contains(testListB, result)
	if (isValid == false){
		t.Fatal("Failed to get random item from string list- Invalid result: " + result)
	}
}

func TestSliceFunctions(t *testing.T){

	testListA := []string{"1", "2"}

	newListA, err := helpers.DeleteIndexFromStringList(testListA, 0)
	if (err != nil) {
		t.Fatal("Failed to delete index from string list: " + err.Error())
	}

	expectedListA := []string{"2"}

	areEqual := slices.Equal(newListA, expectedListA)
	if (areEqual == false){
		t.Fatal("Failed to delete index from string list.")
	}

	testListB := []string{"1", "2", "3", "4"}

	newListB, err := helpers.DeleteIndexFromStringList(testListB, 3)
	if (err != nil) {
		t.Fatal("Failed to delete index from string list: " + err.Error())
	}

	expectedListB := []string{"1", "2", "3"}

	areEqual = slices.Equal(newListB, expectedListB)
	if (areEqual == false){
		t.Fatal("Failed to delete index from string list.")
	}

	testListC := []string{"1"}

	newListC, err := helpers.DeleteIndexFromStringList(testListC, 0)
	if (err != nil) {
		t.Fatal("Failed to delete index from string list: " + err.Error())
	}

	if (len(newListC) != 0){ 
		t.Fatal("Failed to delete index from string list.")
	}
	
	testListD := []string{"1", "2", "3", "4"}

	newListD, err := helpers.DeleteIndexFromStringList(testListD, 0)
	if (err != nil) {
		t.Fatal("Failed to delete index from string list: " + err.Error())
	}

	expectedListD := []string{"2", "3", "4"}

	areEqual = slices.Equal(newListD, expectedListD)
	if (areEqual == false){
		t.Fatal("Failed to delete index from string list.")
	}
}


func TestNumberProportionalScaling(t *testing.T){


	result, err := helpers.ScaleIntProportionally(true, 50, 0, 100, 0, 50)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 25){
		t.Fatal("ScaleIntProportionally failed test 1.")
	}

	result, err = helpers.ScaleIntProportionally(true, 25, 0, 100, 0, 200)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 50){
		t.Fatal("ScaleIntProportionally failed test 2.")
	}

	result, err = helpers.ScaleIntProportionally(false, 25, 0, 100, 0, 200)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 150){
		t.Fatal("ScaleIntProportionally failed test 3.")
	}

	result, err = helpers.ScaleIntProportionally(true, 1, 0, 10, 0, 200)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 20){
		t.Fatal("ScaleIntProportionally failed test 4.")
	}

	result, err = helpers.ScaleIntProportionally(true, -50, -100, 0, 0, 200)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 100){
		t.Fatal("ScaleIntProportionally failed test 5.")
	}
	
	
	result, err = helpers.ScaleIntProportionally(true, -25, -100, 0, 0, 200)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 150){
		t.Fatal("ScaleIntProportionally failed test 6.")
	}

	result, err = helpers.ScaleIntProportionally(true, 50, 0, 100, 0, 2)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 1){
		t.Fatal("ScaleIntProportionally failed test 7.")
	}


	result, err = helpers.ScaleIntProportionally(true, 10, 0, 100, 5, 25)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 7){
		t.Fatal("ScaleIntProportionally failed test 8.")
	}

	result, err = helpers.ScaleIntProportionally(true, 100, 0, 100, 2, 22)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 22){
		t.Fatal("ScaleIntProportionally failed test 9.")
	}

	result, err = helpers.ScaleIntProportionally(false, 0, 0, 100, 2, 22)	
	if (err != nil){
		t.Fatal("ScaleIntProportionally failed: " + err.Error())
	}
	if (result != 22){
		t.Fatal("ScaleIntProportionally failed test 10.")
	}
}


func TestSplitListIntoSublists(t *testing.T){

	inputList := make([]string, 0, 100)

	for i := 0; i < 100; i++{

		item := helpers.ConvertIntToString(i+1)

		inputList = append(inputList, item)
	}

	sublistsList, err := helpers.SplitListIntoSublists(inputList, 10)
	if (err != nil) {
		t.Fatal("Failed to split string list into sublists: " + err.Error())
	}

	totalElements := 0

	for _, element := range sublistsList{

		elementsInSublist := len(element)
		totalElements += elementsInSublist

		if (elementsInSublist != 10){
			t.Fatal("Failed to split string list into sublists: invalid sublist length.")
		}
	}

	if (totalElements != 100){
		t.Fatal("Failed to split string list into sublists: invalid sublist elements length.")
	}
}
