package encoding

import (
	"bytes"
	"github.com/b2broker/simplefix-go/fix"
	"testing"
)

const visibleDelimiter = "|"

func TestUnmarshalItems(t *testing.T) {
	var exampleRawMas = []byte("8=FIX.4.49=6135=A49=Client56=Server34=152=20210706-19:06:12.838108=510=206")

	testData := []struct {
		raw    []byte
		expect []byte
		items  fix.Items
	}{
		{
			raw: exampleRawMas,
			items: fix.Items{
				&fix.KeyValue{Key: "8", Value: &fix.String{}},
				&fix.KeyValue{Key: "9", Value: &fix.String{}},
				&fix.KeyValue{Key: "35", Value: &fix.String{}},
				&fix.KeyValue{Key: "49", Value: &fix.String{}},
				&fix.KeyValue{Key: "56", Value: &fix.String{}},
				&fix.KeyValue{Key: "34", Value: &fix.String{}},
				&fix.KeyValue{Key: "52", Value: &fix.String{}},
				&fix.KeyValue{Key: "108", Value: &fix.String{}},
				&fix.KeyValue{Key: "10", Value: &fix.String{}},
			},
			expect: exampleRawMas,
		},
		{
			raw: exampleRawMas,
			items: fix.Items{
				&fix.KeyValue{Key: "8", Value: &fix.String{}},
				&fix.KeyValue{Key: "35", Value: &fix.String{}},
				&fix.KeyValue{Key: "9", Value: &fix.String{}},
				&fix.KeyValue{Key: "56", Value: &fix.String{}},
				&fix.KeyValue{Key: "49", Value: &fix.String{}},
				&fix.KeyValue{Key: "34", Value: &fix.String{}},
				&fix.KeyValue{Key: "52", Value: &fix.String{}},
				&fix.KeyValue{Key: "100500", Value: &fix.String{}},
				&fix.KeyValue{Key: "108", Value: &fix.String{}},
				&fix.KeyValue{Key: "10", Value: &fix.String{}},
			},
			expect: []byte("8=FIX.4.435=A9=6156=Server49=Client34=152=20210706-19:06:12.838108=510=206"),
		},
		{
			raw: exampleRawMas,
			items: fix.Items{
				&fix.KeyValue{Key: "8", Value: &fix.String{}},
				&fix.KeyValue{Key: "9", Value: &fix.String{}},
				&fix.KeyValue{Key: "35", Value: &fix.String{}},
				&fix.KeyValue{Key: "56", Value: &fix.String{}},
				&fix.KeyValue{Key: "49", Value: &fix.String{}},
				&fix.KeyValue{Key: "34", Value: &fix.String{}},
				&fix.KeyValue{Key: "108", Value: &fix.String{}},
				&fix.KeyValue{Key: "52", Value: &fix.String{}},
				&fix.KeyValue{Key: "10", Value: &fix.String{}},
			},
			expect: []byte("8=FIX.4.49=6135=A56=Server49=Client34=1108=552=20210706-19:06:12.83810=206"),
		},
		{
			raw: []byte("8=FIX.4.49=6135=A56=Server161=4162=A163=1162=B163=2162=C162=DE163=310=206"),
			items: fix.Items{
				&fix.KeyValue{Key: "8", Value: &fix.String{}},
				&fix.KeyValue{Key: "9", Value: &fix.String{}},
				&fix.KeyValue{Key: "35", Value: &fix.String{}},
				&fix.KeyValue{Key: "56", Value: &fix.String{}},
				fix.NewGroup("161", &fix.KeyValue{Key: "162", Value: &fix.String{}}, &fix.KeyValue{Key: "163", Value: &fix.String{}}),
				&fix.KeyValue{Key: "10", Value: &fix.String{}},
			},
			expect: []byte("8=FIX.4.49=6135=A56=Server161=4162=A163=1162=B163=2162=C162=DE163=310=206"),
		},
		{
			raw: []byte("8=FIX.4.49=6135=A56=Server161=4162=A163=1162=B163=2162=C162=DE163=310=206"),
			items: fix.Items{
				&fix.KeyValue{Key: "8", Value: &fix.String{}},
				&fix.KeyValue{Key: "9", Value: &fix.String{}},
				&fix.KeyValue{Key: "35", Value: &fix.String{}},
				&fix.KeyValue{Key: "56", Value: &fix.String{}},
				fix.NewGroup("161", fix.NewComponent(
					&fix.KeyValue{Key: "162", Value: &fix.String{}},
					&fix.KeyValue{Key: "163", Value: &fix.String{}},
				)),
				&fix.KeyValue{Key: "10", Value: &fix.String{}},
			},
			expect: []byte("8=FIX.4.49=6135=A56=Server161=4162=A163=1162=B163=2162=C162=DE163=310=206"),
		},
		{
			raw: []byte("8=FIX.4.49=18335=i34=8649=XC22952=20220314-11:39:13.38556=Q048296=2302=62295=1299=0134=1.0135=1.0188=4588680190=4591680302=64295=1299=0134=100000135=100000188=1.39851190=1.3986510=085"),
			items: fix.Items{
				&fix.KeyValue{Key: "8", Value: &fix.String{}},
				&fix.KeyValue{Key: "9", Value: &fix.String{}},
				&fix.KeyValue{Key: "35", Value: &fix.String{}},
				&fix.KeyValue{Key: "34", Value: &fix.String{}},
				&fix.KeyValue{Key: "49", Value: &fix.String{}},
				&fix.KeyValue{Key: "52", Value: &fix.String{}},
				&fix.KeyValue{Key: "56", Value: &fix.String{}},
				fix.NewGroup("296", fix.NewComponent(
					&fix.KeyValue{Key: "302", Value: &fix.String{}},
					fix.NewComponent(
						&fix.KeyValue{Key: "295", Value: &fix.String{}},
						&fix.KeyValue{Key: "299", Value: &fix.String{}},
						&fix.KeyValue{Key: "134", Value: &fix.Float{}},
						&fix.KeyValue{Key: "135", Value: &fix.Float{}},
						&fix.KeyValue{Key: "188", Value: &fix.Float{}},
						&fix.KeyValue{Key: "190", Value: &fix.Float{}},
					),
				)),
				&fix.KeyValue{Key: "10", Value: &fix.String{}},
			},
			expect: []byte("8=FIX.4.49=18335=i34=8649=XC22952=20220314-11:39:13.38556=Q048296=2302=62295=1299=0134=1.0135=1.0188=4588680190=4591680302=64295=1299=0134=100000135=100000188=1.39851190=1.3986510=085"),
		},
	}

	for i, item := range testData {
		err := unmarshalItems(item.items, item.raw, true)
		if err != nil {
			t.Fatal(err)
		}

		res := item.items.ToBytes()
		if !bytes.Equal(item.expect, res) {
			t.Logf("%d. expect %s (%d)", i, showDelimiter(item.expect), len(item.expect))
			t.Logf("%d. result %s (%d)", i, showDelimiter(res), len(res))
			t.Fatal("the result is not equal to expected message")
		}
	}

}

func showDelimiter(in []byte) []byte {
	return bytes.ReplaceAll(in, fix.Delimiter, []byte(visibleDelimiter))
}
