package blocks

import (
	field_params "github.com/OffchainLabs/prysm/v7/config/fieldparams"
	"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
	"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
	enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
	eth "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
	"github.com/pkg/errors"
)

var (
	_ = interfaces.ReadOnlySignedBeaconBlock(&SignedBeaconBlock{})
	_ = interfaces.ReadOnlyBeaconBlock(&BeaconBlock{})
	_ = interfaces.ReadOnlyBeaconBlockBody(&BeaconBlockBody{})
)

var (
	errPayloadWrongType       = errors.New("execution payload has wrong type")
	errPayloadHeaderWrongType = errors.New("execution payload header has wrong type")
)

const (
	incorrectBlockVersion = "incorrect beacon block version"
	incorrectBodyVersion  = "incorrect beacon block body version"
)

var (
	// ErrUnsupportedVersion for beacon block methods.
	ErrUnsupportedVersion    = errors.New("unsupported beacon block version")
	errNilBlob               = errors.New("received nil blob sidecar")
	errNilDataColumn         = errors.New("received nil data column sidecar")
	errNilBlock              = errors.New("received nil beacon block")
	errNilBlockBody          = errors.New("received nil beacon block body")
	errIncorrectBlockVersion = errors.New(incorrectBlockVersion)
	errIncorrectBodyVersion  = errors.New(incorrectBodyVersion)
	errNilBlockHeader        = errors.New("received nil beacon block header")
	errMissingBlockSignature = errors.New("received nil beacon block signature")
)

// BeaconBlockBody is the main beacon block body structure. It can represent any block type.
type BeaconBlockBody struct {
	version                   int
	randaoReveal              [field_params.BLSSignatureLength]byte
	eth1Data                  *eth.Eth1Data
	graffiti                  [field_params.RootLength]byte
	proposerSlashings         []*eth.ProposerSlashing
	attesterSlashings         []*eth.AttesterSlashing
	attesterSlashingsElectra  []*eth.AttesterSlashingElectra
	attestations              []*eth.Attestation
	attestationsElectra       []*eth.AttestationElectra
	deposits                  []*eth.Deposit
	voluntaryExits            []*eth.SignedVoluntaryExit
	syncAggregate             *eth.SyncAggregate
	executionPayload          interfaces.ExecutionData
	executionPayloadHeader    interfaces.ExecutionData
	blsToExecutionChanges     []*eth.SignedBLSToExecutionChange
	blobKzgCommitments        [][]byte
	executionRequests         *enginev1.ExecutionRequests
	signedExecutionPayloadBid *eth.SignedExecutionPayloadBid
	payloadAttestations       []*eth.PayloadAttestation
}

var _ interfaces.ReadOnlyBeaconBlockBody = &BeaconBlockBody{}

// BeaconBlock is the main beacon block structure. It can represent any block type.
type BeaconBlock struct {
	version       int
	slot          primitives.Slot
	proposerIndex primitives.ValidatorIndex
	parentRoot    [field_params.RootLength]byte
	stateRoot     [field_params.RootLength]byte
	body          *BeaconBlockBody
}

// SignedBeaconBlock is the main signed beacon block structure. It can represent any block type.
type SignedBeaconBlock struct {
	version   int
	block     *BeaconBlock
	signature [field_params.BLSSignatureLength]byte
}
