// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2025, Berachain Foundation. All rights reserved.
// Use of this software is governed by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

package storage

import (
	"context"

	"github.com/berachain/beacon-kit/chain"
	"github.com/berachain/beacon-kit/consensus-types/types"
	dastore "github.com/berachain/beacon-kit/da/store"
	"github.com/berachain/beacon-kit/log"
	statedb "github.com/berachain/beacon-kit/state-transition/core/state"
	"github.com/berachain/beacon-kit/storage/beacondb"
	"github.com/berachain/beacon-kit/storage/block"
	"github.com/berachain/beacon-kit/storage/deposit"
)

// Backend is a struct that holds the storage backend. It provides a simple
// interface to access all types of storage required by the runtime.
type Backend struct {
	chainSpec         chain.Spec
	availabilityStore *dastore.Store
	kvStore           *beacondb.KVStore
	depositStore      deposit.StoreManager
	blockStore        *block.KVStore[*types.BeaconBlock]
	logger            log.Logger
	telemetrySink     statedb.TelemetrySink
}

func NewBackend(
	chainSpec chain.Spec,
	availabilityStore *dastore.Store,
	kvStore *beacondb.KVStore,
	depositStore deposit.StoreManager,
	blockStore *block.KVStore[*types.BeaconBlock],
	logger log.Logger,
	telemetrySink statedb.TelemetrySink,
) *Backend {
	return &Backend{
		chainSpec:         chainSpec,
		availabilityStore: availabilityStore,
		kvStore:           kvStore,
		depositStore:      depositStore,
		blockStore:        blockStore,
		logger:            logger,
		telemetrySink:     telemetrySink,
	}
}

// AvailabilityStore returns the availability store struct initialized with a
// given context.
func (k Backend) AvailabilityStore() *dastore.Store {
	return k.availabilityStore
}

// StateFromContext returns the beacon state struct initialized with a given
// context and the store key.
func (k Backend) StateFromContext(ctx context.Context) *statedb.StateDB {
	return statedb.NewBeaconStateFromDB(
		k.kvStore.WithContext(ctx),
		k.chainSpec,
		k.logger,
		k.telemetrySink,
	)
}

// BeaconStore returns the beacon store struct.
func (k Backend) BeaconStore() *beacondb.KVStore {
	return k.kvStore
}

func (k Backend) BlockStore() *block.KVStore[*types.BeaconBlock] {
	return k.blockStore
}

// DepositStore returns the deposit store struct initialized with a.
func (k Backend) DepositStore() deposit.StoreManager {
	return k.depositStore
}
