package morph

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

	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
	"github.com/nspcc-dev/neo-go/pkg/wallet"
	"github.com/spf13/viper"
)

func getAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) {
	wallets, err := openAlphabetWallets(v, walletDir)
	if err != nil {
		return nil, err
	}

	if len(wallets) > maxAlphabetNodes {
		return nil, ErrTooManyAlphabetNodes
	}
	return wallets, nil
}

func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) {
	walletFiles, err := os.ReadDir(walletDir)
	if err != nil {
		return nil, fmt.Errorf("can't read alphabet wallets dir: %w", err)
	}

	var size int
loop:
	for i := 0; i < len(walletFiles); i++ {
		name := innerring.GlagoliticLetter(i).String() + ".json"
		for j := range walletFiles {
			if walletFiles[j].Name() == name {
				size++
				continue loop
			}
		}
		break
	}
	if size == 0 {
		return nil, errors.New("alphabet wallets dir is empty (run `generate-alphabet` command first)")
	}

	wallets := make([]*wallet.Wallet, size)
	for i := 0; i < size; i++ {
		letter := innerring.GlagoliticLetter(i).String()
		p := filepath.Join(walletDir, letter+".json")
		w, err := wallet.NewWalletFromFile(p)
		if err != nil {
			return nil, fmt.Errorf("can't open wallet: %w", err)
		}

		password, err := config.GetPassword(v, letter)
		if err != nil {
			return nil, fmt.Errorf("can't fetch password: %w", 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)
			}
		}

		wallets[i] = w
	}

	return wallets, nil
}

func newActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) {
	return actor.New(c, []actor.SignerAccount{{
		Signer: transaction.Signer{
			Account: committeeAcc.Contract.ScriptHash(),
			Scopes:  transaction.Global,
		},
		Account: committeeAcc,
	}})
}