// Copyright 2024 The Erigon Authors
// This file is part of Erigon.
//
// Erigon is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Erigon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Erigon. If not, see <http://www.gnu.org/licenses/>.

package chain

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/erigontech/erigon/common"
	chainspec "github.com/erigontech/erigon/execution/chain/spec"
	"github.com/erigontech/erigon/execution/types/accounts"
)

func TestGetBurntContract(t *testing.T) {
	// Ethereum
	assert.Equal(t, accounts.NilAddress, chainspec.Mainnet.Config.GetBurntContract(0))
	assert.Equal(t, accounts.NilAddress, chainspec.Mainnet.Config.GetBurntContract(10_000_000))

	// Gnosis Chain
	addr := chainspec.Gnosis.Config.GetBurntContract(19_040_000)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92"), addr.Value())
	addr = chainspec.Gnosis.Config.GetBurntContract(19_040_001)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92"), addr.Value())

	// Bor Mainnet
	addr = BorMainnet.Config.GetBurntContract(23850000)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"), addr.Value())
	addr = BorMainnet.Config.GetBurntContract(23850000 + 1)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"), addr.Value())
	addr = BorMainnet.Config.GetBurntContract(50523000 - 1)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"), addr.Value())
	addr = BorMainnet.Config.GetBurntContract(50523000)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x7A8ed27F4C30512326878652d20fC85727401854"), addr.Value())
	addr = BorMainnet.Config.GetBurntContract(50523000 + 1)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x7A8ed27F4C30512326878652d20fC85727401854"), addr.Value())

	// Amoy
	addr = Amoy.Config.GetBurntContract(0)
	require.NotNil(t, addr)
	assert.Equal(t, common.HexToAddress("0x000000000000000000000000000000000000dead"), addr.Value())
}

func TestCalculateCoinbaseAmoy(t *testing.T) {
	config := Amoy.Config

	addr0 := common.Address{}
	expectedCoinbaseAddr := common.HexToAddress("0x7Ee41D8A25641000661B1EF5E6AE8A00400466B0")
	var testCases = []struct {
		blockNumber uint64
		expected    common.Address
		description string
	}{
		{0, addr0, "at genesis block"},
		{10_000, addr0, "before transition"},
		{26272255, addr0, "just before transition"},
		{26272256, expectedCoinbaseAddr, "at transition"},
		{30000000, expectedCoinbaseAddr, "after transition"},
	}
	for _, tc := range testCases {
		result := config.Bor.CalculateCoinbase(tc.blockNumber)
		if result != accounts.InternAddress(tc.expected) {
			t.Errorf("Block %d (%s): expected %s, got %s",
				tc.blockNumber, tc.description, tc.expected, result)
		}
	}

}
