// Copyright 2024 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

package db

import (
	"fmt"

	"github.com/ChainSafe/gossamer/internal/primitives/core/hash"
	"github.com/ChainSafe/gossamer/internal/primitives/database"
	"github.com/ChainSafe/gossamer/pkg/scale"
)

// Functionality for reading and storing children hashes from db.

// Returns the hashes of the children blocks of the block with parentHash.
func readChildren[H comparable](
	db database.Database[hash.H256], column database.ColumnID, prefix []byte, parentHash H,
) ([]H, error) {
	encoded := scale.MustMarshal(parentHash)
	key := append(prefix, encoded...)

	rawVal := db.Get(column, key)
	if rawVal == nil {
		return nil, nil
	}

	var children []H
	err := scale.Unmarshal(rawVal, &children)
	if err != nil {
		return nil, fmt.Errorf("error decoding children: %w", err)
	}

	return children, nil
}

// Inserts parentHash and childrenHashes in the transaction.
// Any existing value is overwritten upon write.
func writeChildren[H comparable](
	tx *database.Transaction[hash.H256], column database.ColumnID, prefix []byte, parentHash H, childrenHashes []H,
) {
	encoded := scale.MustMarshal(parentHash)
	key := append(prefix, encoded...)
	tx.Set(column, key, scale.MustMarshal(childrenHashes))
}

// Prepare transaction to remove the children of parentHash.
func removeChildren[H comparable](
	tx *database.Transaction[hash.H256], column database.ColumnID, prefix []byte, parentHash H,
) {
	encoded := scale.MustMarshal(parentHash)
	key := append(prefix, encoded...)
	tx.Remove(column, key)
}
