package helper

import (
	"fmt"
	"os"
	"path/filepath"

	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
	"github.com/nspcc-dev/neo-go/pkg/wallet"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

func InitializeContractWallet(v *viper.Viper, walletDir string) (*wallet.Wallet, error) {
	password, err := config.GetPassword(v, constants.ContractWalletPasswordKey)
	if err != nil {
		return nil, err
	}

	w, err := wallet.NewWallet(filepath.Join(walletDir, constants.ContractWalletFilename))
	if err != nil {
		return nil, err
	}

	acc, err := wallet.NewAccount()
	if err != nil {
		return nil, err
	}

	err = acc.Encrypt(password, keys.NEP2ScryptParams())
	if err != nil {
		return nil, err
	}

	w.AddAccount(acc)
	if err := w.SavePretty(); err != nil {
		return nil, err
	}

	return w, nil
}

func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*wallet.Wallet, error) {
	p := filepath.Join(walletDir, constants.ContractWalletFilename)
	w, err := wallet.NewWalletFromFile(p)
	if err != nil {
		if !os.IsNotExist(err) {
			return nil, fmt.Errorf("can't open wallet: %w", err)
		}

		cmd.Printf("Contract group wallet is missing, initialize at %s\n", p)
		return InitializeContractWallet(v, walletDir)
	}

	password, err := config.GetPassword(v, constants.ContractWalletPasswordKey)
	if err != nil {
		return nil, err
	}

	for i := range w.Accounts {
		if err := w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil {
			return nil, fmt.Errorf("can't unlock wallet: %w", err)
		}
	}

	return w, nil
}

func getWallet(cmd *cobra.Command, v *viper.Viper, needContracts bool, walletDir string) (*wallet.Wallet, error) {
	if !needContracts {
		return nil, nil
	}
	return openContractWallet(v, cmd, walletDir)
}