package meta_test

import (
	"context"
	"testing"

	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
	cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
	objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
	oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
	"github.com/stretchr/testify/require"
)

func TestDB_SelectExpired(t *testing.T) {
	db := newDB(t)
	defer func() { require.NoError(t, db.Close()) }()

	containerID1 := cidtest.ID()

	expiredObj11 := testutil.GenerateObject()
	expiredObj11.SetContainerID(containerID1)
	setExpiration(expiredObj11, 10)
	err := putBig(db, expiredObj11)
	require.NoError(t, err)

	expiredObj12 := testutil.GenerateObject()
	expiredObj12.SetContainerID(containerID1)
	setExpiration(expiredObj12, 12)
	err = putBig(db, expiredObj12)
	require.NoError(t, err)

	notExpiredObj11 := testutil.GenerateObject()
	notExpiredObj11.SetContainerID(containerID1)
	setExpiration(notExpiredObj11, 20)
	err = putBig(db, notExpiredObj11)
	require.NoError(t, err)

	regularObj11 := testutil.GenerateObject()
	regularObj11.SetContainerID(containerID1)
	err = putBig(db, regularObj11)
	require.NoError(t, err)

	containerID2 := cidtest.ID()

	expiredObj21 := testutil.GenerateObject()
	expiredObj21.SetContainerID(containerID2)
	setExpiration(expiredObj21, 10)
	err = putBig(db, expiredObj21)
	require.NoError(t, err)

	expiredObj22 := testutil.GenerateObject()
	expiredObj22.SetContainerID(containerID2)
	setExpiration(expiredObj22, 12)
	err = putBig(db, expiredObj22)
	require.NoError(t, err)

	notExpiredObj21 := testutil.GenerateObject()
	notExpiredObj21.SetContainerID(containerID2)
	setExpiration(notExpiredObj21, 20)
	err = putBig(db, notExpiredObj21)
	require.NoError(t, err)

	regularObj21 := testutil.GenerateObject()
	regularObj21.SetContainerID(containerID2)
	err = putBig(db, regularObj21)
	require.NoError(t, err)

	expired, err := db.FilterExpired(context.Background(), 15,
		[]oid.Address{
			getAddressSafe(t, expiredObj11), getAddressSafe(t, expiredObj12), getAddressSafe(t, notExpiredObj11), getAddressSafe(t, regularObj11),
			getAddressSafe(t, expiredObj21), getAddressSafe(t, expiredObj22), getAddressSafe(t, notExpiredObj21), getAddressSafe(t, regularObj21),
		})
	require.NoError(t, err)
	require.Equal(t, 4, len(expired), "invalid expired count")
	require.Contains(t, expired, getAddressSafe(t, expiredObj11))
	require.Contains(t, expired, getAddressSafe(t, expiredObj12))
	require.Contains(t, expired, getAddressSafe(t, expiredObj21))
	require.Contains(t, expired, getAddressSafe(t, expiredObj22))
}

func getAddressSafe(t *testing.T, o *objectSDK.Object) oid.Address {
	cid, set := o.ContainerID()
	if !set {
		t.Fatalf("container id required")
	}
	id, set := o.ID()
	if !set {
		t.Fatalf("object id required")
	}
	var addr oid.Address
	addr.SetContainer(cid)
	addr.SetObject(id)
	return addr
}