package rawtemporaldb_test

import (
	"context"
	"encoding/binary"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/erigontech/erigon/common/log/v3"
	"github.com/erigontech/erigon/db/datadir"
	"github.com/erigontech/erigon/db/kv"
	"github.com/erigontech/erigon/db/kv/temporal/temporaltest"
	"github.com/erigontech/erigon/db/rawdb/rawtemporaldb"
	"github.com/erigontech/erigon/db/state/execctx"
)

func TestAppendReceipt(t *testing.T) {
	dirs, require := datadir.New(t.TempDir()), require.New(t)
	db := temporaltest.NewTestDB(t, dirs)
	tx, err := db.BeginTemporalRw(context.Background())
	require.NoError(err)
	defer tx.Rollback()

	ttx := tx
	doms, err := execctx.NewSharedDomains(context.Background(), ttx, log.New())
	require.NoError(err)
	defer doms.Close()

	err = rawtemporaldb.AppendReceipt(doms.AsPutDel(ttx), 1, 10, 0, 0) // 1 log
	require.NoError(err)

	err = rawtemporaldb.AppendReceipt(doms.AsPutDel(ttx), 1, 11, 0, 1) // 0 log
	require.NoError(err)

	err = rawtemporaldb.AppendReceipt(doms.AsPutDel(ttx), 4, 12, 0, 3) // 3 logs
	require.NoError(err)

	err = rawtemporaldb.AppendReceipt(doms.AsPutDel(ttx), 4, 14, 0, 4) // 0 log
	require.NoError(err)

	err = doms.Flush(context.Background(), tx)
	require.NoError(err)

	v, ok, err := ttx.HistorySeek(kv.ReceiptDomain, rawtemporaldb.LogIndexAfterTxKey, 0)
	require.NoError(err)
	require.True(ok)
	require.Empty(v)

	v, ok, err = ttx.HistorySeek(kv.ReceiptDomain, rawtemporaldb.LogIndexAfterTxKey, 1)
	require.NoError(err)
	require.True(ok)
	require.Equal(uint64(1), uvarint(v))

	v, ok, err = ttx.HistorySeek(kv.ReceiptDomain, rawtemporaldb.LogIndexAfterTxKey, 2)
	require.NoError(err)
	require.True(ok)
	require.Equal(uint64(1), uvarint(v))

	v, ok, err = ttx.HistorySeek(kv.ReceiptDomain, rawtemporaldb.LogIndexAfterTxKey, 3)
	require.NoError(err)
	require.True(ok)
	require.Equal(uint64(1), uvarint(v))

	_, ok, err = ttx.HistorySeek(kv.ReceiptDomain, rawtemporaldb.LogIndexAfterTxKey, 4)
	require.NoError(err)
	require.False(ok)

	_, ok, err = ttx.HistorySeek(kv.ReceiptDomain, rawtemporaldb.LogIndexAfterTxKey, 5)
	require.NoError(err)
	require.False(ok)

	//block1
	cumGasUsed, _, logIdxAfterTx, err := rawtemporaldb.ReceiptAsOf(ttx, 0)
	require.NoError(err)
	require.Equal(uint32(0), logIdxAfterTx)
	require.Equal(uint64(0), cumGasUsed)

	cumGasUsed, _, logIdxAfterTx, err = rawtemporaldb.ReceiptAsOf(ttx, 1)
	require.NoError(err)
	require.Equal(uint32(1), logIdxAfterTx)
	require.Equal(uint64(10), cumGasUsed)

	cumGasUsed, _, logIdxAfterTx, err = rawtemporaldb.ReceiptAsOf(ttx, 2)
	require.NoError(err)
	require.Equal(uint32(1), logIdxAfterTx)
	require.Equal(uint64(11), cumGasUsed)

	//block2
	cumGasUsed, _, logIdxAfterTx, err = rawtemporaldb.ReceiptAsOf(ttx, 3)
	require.NoError(err)
	require.Equal(uint32(1), logIdxAfterTx)
	require.Equal(uint64(11), cumGasUsed)

	cumGasUsed, _, logIdxAfterTx, err = rawtemporaldb.ReceiptAsOf(ttx, 4)
	require.NoError(err)
	require.Equal(uint32(4), logIdxAfterTx)
	require.Equal(uint64(12), cumGasUsed)

	cumGasUsed, _, logIdxAfterTx, err = rawtemporaldb.ReceiptAsOf(ttx, 5)
	require.NoError(err)
	require.Equal(uint32(4), logIdxAfterTx)
	require.Equal(uint64(14), cumGasUsed)

	// reader

}
func uvarint(in []byte) (res uint64) {
	res, _ = binary.Uvarint(in)
	return res
}
