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

// t_operator_test.go
package expr

import (
	"testing"

	"git.portale-stac.it/go-pkg/expr/types/array"
	"git.portale-stac.it/go-pkg/expr/types/dict"
)

func TestOperator(t *testing.T) {
	section := "Operator"
	inputs := []inputType{
		/*   1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`},
		/*   2 */ {`a=1; unset ["a", "b"]`, int64(1), nil},
		/*   3 */ {`f=func(){3}; unset "f()"`, int64(1), nil},
		/*   4 */ {`a=1; a<<=1+0`, int64(2), nil},
		/*   5 */ {`a=2; a>>=1+0`, int64(1), nil},
		/*   6 */ {`1<<1`, int64(2), nil},
		/*   7 */ {`1>>1`, int64(0), nil},
		/*   8 */ {`1|2`, int64(3), nil},
		/*   9 */ {`a=1; a|=2`, int64(3), nil},
		/*  10 */ {`3&1`, int64(1), nil},
		/*  11 */ {`a=3; a&=1`, int64(1), nil},
		/*  12 */ {`~1`, int64(-2), nil},
		/*  13 */ {`0x10`, int64(16), nil},
		/*  14 */ {`0x1X`, nil, `[1:5] two adjacent operators: "1" and "X"`},
		/*  15 */ {`0o10`, int64(8), nil},
		/*  16 */ {`0b10`, int64(2), nil},
		/*  17 */ {`~true`, nil, `[1:2] prefix/postfix operator "~" does not support operand 'true' [bool]`},
		/*  18 */ {`1^2`, int64(3), nil},
		/*  19 */ {`3^2`, int64(1), nil},
		/*  20 */ {`a=1; a^=2`, int64(3), nil},
		/*  21 */ {`a=1; ++a`, int64(2), nil},
		/*  22 */ {`a=1; --a`, int64(0), nil},
		/*  23 */ {`a=1; a++`, int64(1), nil},
		/*  24 */ {`a=1; a--`, int64(1), nil},
		/*  25 */ {`a="1"; ++a`, nil, `[1:9] prefix/postfix operator "++" does not support operand '1' [string]`},
		/*  26 */ {`a="1"; --a`, nil, `[1:9] prefix/postfix operator "--" does not support operand '1' [string]`},
		/*  27 */ {`a="1"; a++`, nil, `[1:10] prefix/postfix operator "++" does not support operand '1' [string]`},
		/*  28 */ {`a="1"; a--`, nil, `[1:10] prefix/postfix operator "--" does not support operand '1' [string]`},
		/*  29 */ {`2 << 3;`, int64(16), nil},
		/*  30 */ {`2 >> 3;`, int64(0), nil},
	}

	// t.Setenv("EXPR_PATH", ".")

	// runTestSuiteSpec(t, section, inputs, 22)
	RunTestSuite(t, section, inputs)
}

func TestOperatorDigest(t *testing.T) {
	section := "Operator-Digest"
	inputs := []inputType{
		/*   1 */ {`max=0; [2,3,1] digest (max=(($_ > max) ? {$_} :: {max}))`, int64(3), nil},
	}

	// runTestSuiteSpec(t, section, inputs, 29)
	RunTestSuite(t, section, inputs)
}

func TestOperatorGroupBy(t *testing.T) {
	section := "Operator-GroupBy"
	inputs := []inputType{
		/*   1 */ {`L=[{"num": 1, "alpha": "one"}, {"num": 2, "alpha": "two"}, {"num": 3, "alpha": "three"}]; L groupby "num"`,
			dict.NewDict(map[any]any{
				"1": array.NewArrayA(dict.NewDict(map[any]any{"num": int64(1), "alpha": "one"})),
				"2": array.NewArrayA(dict.NewDict(map[any]any{"num": int64(2), "alpha": "two"})),
				"3": array.NewArrayA(dict.NewDict(map[any]any{"num": int64(3), "alpha": "three"})),
			}),
			nil},
		/*   2 */ {`cars = [{"model": "compas", "vendor": "jeep"}, {"model": "limited", "vendor": "jeep"}, {"model": "600", "vendor":"fiat"}]; cars groupby "vendor"`,
			dict.NewDict(map[any]any{
				"jeep": array.NewArrayA(
					dict.NewDict(map[any]any{"model": "compas", "vendor": "jeep"}),
					dict.NewDict(map[any]any{"model": "limited", "vendor": "jeep"})),
				"fiat": array.NewArrayA(dict.NewDict(map[any]any{"model": "600", "vendor": "fiat"})),
			}),
			nil},
		/*  3 */ {`[3,4,5] groupby $__`,
			dict.NewDict(map[any]any{
				"0": array.NewArrayA(int64(3)),
				"1": array.NewArrayA(int64(4)),
				"2": array.NewArrayA(int64(5)),
			}),
			nil},
	}

	// runTestSuiteSpec(t, section, inputs, 3)
	RunTestSuite(t, section, inputs)
}
