package tree

import (
	"testing"

	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama"
	"github.com/stretchr/testify/require"
)

func Test_mergeOperationStreams(t *testing.T) {
	tests := []struct {
		name          string
		opTimes       [][]uint64
		wantValues    []uint64
		wantMinHeight uint64
	}{
		{
			name: "1",
			opTimes: [][]uint64{
				{250, 251, 255},
				{252, 253, 254, 256, 257},
			},
			wantValues:    []uint64{250, 251, 252, 253, 254, 255, 256, 257},
			wantMinHeight: 255,
		},
		{
			name: "2",
			opTimes: [][]uint64{
				{250, 251, 255, 259},
				{252, 253, 254, 256, 257},
			},
			wantValues:    []uint64{250, 251, 252, 253, 254, 255, 256, 257, 259},
			wantMinHeight: 257,
		},
		{
			name: "3",
			opTimes: [][]uint64{
				{250, 251, 255},
				{249, 250, 251, 253, 254, 256, 257},
			},
			wantValues:    []uint64{249, 250, 250, 251, 251, 253, 254, 255, 256, 257},
			wantMinHeight: 255,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			nodeOpChans := make([]chan *pilorama.Move, len(tt.opTimes))
			for i := range nodeOpChans {
				nodeOpChans[i] = make(chan *pilorama.Move)
			}

			// generate and put values to all chans
			for i, ch := range nodeOpChans {
				i := i
				ch := ch
				go func() {
					for _, tm := range tt.opTimes[i] {
						op := &pilorama.Move{}
						op.Time = tm
						ch <- op
					}
					close(nodeOpChans[i])
				}()
			}

			merged := make(chan *pilorama.Move, 1)
			min := make(chan uint64)
			go func() {
				min <- mergeOperationStreams(nodeOpChans, merged)
			}()

			var res []uint64
			for op := range merged {
				res = append(res, op.Time)
			}
			require.Equal(t, tt.wantValues, res)
			require.Equal(t, tt.wantMinHeight, <-min)
		})
	}
}