// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.

// utils_test.go
package expr

import (
	"errors"
	"testing"
)

func TestIsString(t *testing.T) {
	count := 0
	succeeded := 0
	failed := 0

	count++
	if !IsBool(true) {
		t.Errorf("%d: IsBool(true) -> result = false, want true", count)
		failed++
	} else {
		succeeded++
	}

	count++
	if !IsString("abc") {
		t.Errorf("%d: IsString(\"abc\") -> result = false, want true", count)
		failed++
	} else {
		succeeded++
	}

	count++
	if !IsInteger(int64(123)) {
		t.Errorf("%d: IsInteger(123) -> result = false, want true", count)
		failed++
	} else {
		succeeded++
	}

	count++
	if !IsFloat(1.23) {
		t.Errorf("%d: IsFloat(1.23) -> result = false, want true", count)
		failed++
	} else {
		succeeded++
	}

	count++
	if !IsFloat(numAsFloat(123)) {
		t.Errorf("%d: IsFloat(numAsFloat(123)) -> result = false, want true", count)
		failed++
	} else {
		succeeded++
	}

	count++
	b, ok := toBool(true)
	if !(ok && b) {
		t.Errorf("%d: toBool(true) b=%v, ok=%v -> result = false, want true", count, b, ok)
		failed++
	} else {
		succeeded++
	}

	count++
	b, ok = toBool("abc")
	if !(ok && b) {
		t.Errorf("%d: toBool(\"abc\") b=%v, ok=%v -> result = false, want true", count, b, ok)
		failed++
	} else {
		succeeded++
	}

	t.Logf("test count: %d, succeeded count: %d, failed count: %d", count, succeeded, failed)
}

func TestToIntOk(t *testing.T) {
	source := int64(64)
	wantValue := int(64)
	wantErr := error(nil)

	gotValue, gotErr := toInt(source, "test")

	if gotErr != nil || gotValue != wantValue {
		t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v",
			source, gotValue, gotErr, wantValue, wantErr)
	}
}

func TestToIntErr(t *testing.T) {
	source := uint64(64)
	wantValue := 0
	wantErr := errors.New(`test expected integer, got uint64 (64)`)

	gotValue, gotErr := toInt(source, "test")

	if gotErr.Error() != wantErr.Error() || gotValue != wantValue {
		t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v",
			source, gotValue, gotErr, wantValue, wantErr)
	}
}

func TestAnyInteger(t *testing.T) {
	type inputType struct {
		source    any
		wantValue int64
		wantOk    bool
	}
	section := "utils.anyInteger"

	inputs := []inputType{
		/*  1 */ {int8(-8), int64(-8), true},
		/*  2 */ {int16(-16), int64(-16), true},
		/*  3 */ {int32(-32), int64(-32), true},
		/*  4 */ {int64(-64), int64(-64), true},
		/*  5 */ {uint8(8), int64(8), true},
		/*  6 */ {uint16(16), int64(16), true},
		/*  7 */ {uint32(32), int64(32), true},
		/*  8 */ {uint64(64), int64(64), true},
		/*  9 */ {int(-1), int64(-1), true},
		/* 10 */ {true, 0, false},
	}

	succeeded := 0
	failed := 0

	for i, input := range inputs {
		gotValue, gotOk := anyInteger(input.source)
		if gotOk != input.wantOk || gotValue != input.wantValue {
			t.Errorf("%d: anyInteger(%v) -> gotOk = %t, wantOk = %t; gotValue = %v, wantValue = %v",
				i+1, input.source, gotOk, input.wantOk, gotValue, input.wantValue)
			failed++
		} else {
			succeeded++
		}
	}
	t.Logf("%s -- test count: %d, succeeded: %d, failed: %d", section, len(inputs), succeeded, failed)
}