package gateway

import (
	"strings"

	"github.com/tech/sendico/chain/gateway/internal/keymanager"
	clockpkg "github.com/tech/sendico/pkg/clock"
)

// Option configures the Service.
type Option func(*Service)

// Network describes a supported blockchain network and known token contracts.
type Network struct {
	Name         string
	RPCURL       string
	ChainID      uint64
	NativeToken  string
	TokenConfigs []TokenContract
}

// TokenContract captures the metadata needed to work with a specific on-chain token.
type TokenContract struct {
	Symbol          string
	ContractAddress string
}

// ServiceWallet captures the managed service wallet configuration.
type ServiceWallet struct {
	Network    string
	Address    string
	PrivateKey string
}

// WithKeyManager configures the service key manager.
func WithKeyManager(manager keymanager.Manager) Option {
	return func(s *Service) {
		s.keyManager = manager
	}
}

// WithTransferExecutor configures the executor responsible for on-chain submissions.
func WithTransferExecutor(executor TransferExecutor) Option {
	return func(s *Service) {
		s.executor = executor
	}
}

// WithNetworks configures supported blockchain networks.
func WithNetworks(networks []Network) Option {
	return func(s *Service) {
		if len(networks) == 0 {
			return
		}
		if s.networks == nil {
			s.networks = make(map[string]Network, len(networks))
		}
		for _, network := range networks {
			if network.Name == "" {
				continue
			}
			clone := network
			if clone.TokenConfigs == nil {
				clone.TokenConfigs = []TokenContract{}
			}
			for i := range clone.TokenConfigs {
				clone.TokenConfigs[i].Symbol = strings.ToUpper(strings.TrimSpace(clone.TokenConfigs[i].Symbol))
				clone.TokenConfigs[i].ContractAddress = strings.ToLower(strings.TrimSpace(clone.TokenConfigs[i].ContractAddress))
			}
			clone.Name = strings.ToLower(strings.TrimSpace(clone.Name))
			s.networks[clone.Name] = clone
		}
	}
}

// WithServiceWallet configures the service wallet binding.
func WithServiceWallet(wallet ServiceWallet) Option {
	return func(s *Service) {
		s.serviceWallet = wallet
	}
}

// WithClock overrides the service clock.
func WithClock(clk clockpkg.Clock) Option {
	return func(s *Service) {
		if clk != nil {
			s.clock = clk
		}
	}
}
