// stm: #unit
package policy

import (
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/filecoin-project/go-state-types/abi"
	"github.com/filecoin-project/go-state-types/network"
	builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
	miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
	paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
	verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
	builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
	miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
	paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych"
	verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg"
)

func TestSupportedProofTypes(t *testing.T) {
	var oldTypes []abi.RegisteredSealProof
	for t := range miner0.SupportedProofTypes {
		oldTypes = append(oldTypes, t)
	}
	//stm: @BLOCKCHAIN_POLICY_SET_MAX_SUPPORTED_PROOF_TYPES_001
	t.Cleanup(func() {
		SetSupportedProofTypes(oldTypes...)
	})

	SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
	require.EqualValues(t,
		miner0.SupportedProofTypes,
		map[abi.RegisteredSealProof]struct{}{
			abi.RegisteredSealProof_StackedDrg2KiBV1: {},
		},
	)
	//stm: @BLOCKCHAIN_POLICY_ADD_MAX_SUPPORTED_PROOF_TYPES_001
	AddSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1)
	require.EqualValues(t,
		miner0.SupportedProofTypes,
		map[abi.RegisteredSealProof]struct{}{
			abi.RegisteredSealProof_StackedDrg2KiBV1: {},
			abi.RegisteredSealProof_StackedDrg8MiBV1: {},
		},
	)
}

// Tests assumptions about policies being the same between actor versions.
func TestAssumptions(t *testing.T) {
	//stm: @BLOCKCHAIN_POLICY_ASSUMPTIONS_001
	require.EqualValues(t, miner0.SupportedProofTypes, miner2.PreCommitSealProofTypesV0)
	require.Equal(t, miner0.PreCommitChallengeDelay, miner2.PreCommitChallengeDelay)
	require.Equal(t, miner0.MaxSectorExpirationExtension, miner2.MaxSectorExpirationExtension)
	require.Equal(t, miner0.ChainFinality, miner2.ChainFinality)
	require.Equal(t, miner0.WPoStChallengeWindow, miner2.WPoStChallengeWindow)
	require.Equal(t, miner0.WPoStProvingPeriod, miner2.WPoStProvingPeriod)
	require.Equal(t, miner0.WPoStPeriodDeadlines, miner2.WPoStPeriodDeadlines)
	require.Equal(t, miner0.AddressedSectorsMax, miner2.AddressedSectorsMax)
	require.Equal(t, paych0.SettleDelay, paych2.SettleDelay)
	require.True(t, verifreg0.MinVerifiedDealSize.Equals(verifreg2.MinVerifiedDealSize))
}

func TestPartitionSizes(t *testing.T) {
	//stm: @CHAIN_ACTOR_PARTITION_SIZES_001
	for _, p := range abi.SealProofInfos {
		sizeNew, err := builtin2.PoStProofWindowPoStPartitionSectors(p.WindowPoStProof)
		require.NoError(t, err)
		sizeOld, err := builtin0.PoStProofWindowPoStPartitionSectors(p.WindowPoStProof)
		if err != nil {
			// new proof type.
			continue
		}
		require.Equal(t, sizeOld, sizeNew)
	}
}

func TestPoStSize(t *testing.T) {
	//stm: @BLOCKCHAIN_POLICY_GET_MAX_POST_PARTITIONS_001
	v12PoStSize, err := GetMaxPoStPartitions(network.Version12, abi.RegisteredPoStProof_StackedDrgWindow64GiBV1)
	require.Equal(t, 4, v12PoStSize)
	require.NoError(t, err)
	v13PoStSize, err := GetMaxPoStPartitions(network.Version13, abi.RegisteredPoStProof_StackedDrgWindow64GiBV1)
	require.NoError(t, err)
	require.Equal(t, 10, v13PoStSize)
}
