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

// funcs_test.go
package expr

import (
	"errors"
	"fmt"
	"strings"
	"testing"
)

func TestFuncs(t *testing.T) {
	type inputType struct {
		source     string
		wantResult any
		wantErr    error
	}

	inputs := []inputType{
		/*   1 */ {`isNil(nil)`, true, nil},
		/*   2 */ {`v=nil; isNil(v)`, true, nil},
		/*   3 */ {`v=5; isNil(v)`, false, nil},
		/*   4 */ {`int(true)`, int64(1), nil},
		/*   5 */ {`int(false)`, int64(0), nil},
		/*   6 */ {`int(3.1)`, int64(3), nil},
		/*   7 */ {`int(3.9)`, int64(3), nil},
		/*   8 */ {`int("432")`, int64(432), nil},
		/*   9 */ {`int("1.5")`, nil, errors.New(`strconv.Atoi: parsing "1.5": invalid syntax`)},
		/*  10 */ {`int("432", 4)`, nil, errors.New(`int() requires exactly one param`)},
		/*  11 */ {`int(nil)`, nil, errors.New(`int() can't convert <nil> to int`)},
	}

	succeeded := 0
	failed := 0

	// inputs1 := []inputType{
	// 	/*   1 */ {`0?{}`, nil, nil},
	// }

	for i, input := range inputs {
		var expr Expr
		var gotResult any
		var gotErr error

		ctx := NewSimpleFuncStore()
		// ImportMathFuncs(ctx)
		// ImportImportFunc(ctx)
		// ImportOsFuncs(ctx)
		parser := NewParser(ctx)

		logTest(t, i+1, input.source, input.wantResult, input.wantErr)

		r := strings.NewReader(input.source)
		scanner := NewScanner(r, DefaultTranslations())

		good := true
		if expr, gotErr = parser.Parse(scanner); gotErr == nil {
			gotResult, gotErr = expr.Eval(ctx)
		}

		if gotResult != input.wantResult {
			t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult)
			good = false
		}

		if gotErr != input.wantErr {
			if input.wantErr == nil || gotErr == nil || (gotErr.Error() != input.wantErr.Error()) {
				t.Errorf("%d: %q -> err = <%v>, want <%v>", i+1, input.source, gotErr, input.wantErr)
				good = false
			}
		}

		if good {
			succeeded++
		} else {
			failed++
		}
	}
	t.Log(fmt.Sprintf("test count: %d, succeeded count: %d, failed count: %d", len(inputs), succeeded, failed))
}