package drivers

import (
	"fmt"
	"strings"

	"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
	"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver/tron"
	"github.com/tech/sendico/gateway/tron/shared"
	"github.com/tech/sendico/pkg/merrors"
	"github.com/tech/sendico/pkg/mlogger"
	"go.uber.org/zap"
)

// Registry maps configured network keys to chain drivers.
type Registry struct {
	byNetwork map[string]driver.Driver
}

// NewRegistry selects drivers for the configured networks.
func NewRegistry(logger mlogger.Logger, networks []shared.Network) (*Registry, error) {
	if logger == nil {
		return nil, merrors.InvalidArgument("driver registry: logger is required")
	}
	result := &Registry{byNetwork: map[string]driver.Driver{}}
	for _, network := range networks {
		if !network.Name.IsValid() {
			continue
		}
		name := network.Name.String()
		chainDriver, err := resolveDriver(logger, name)
		if err != nil {
			logger.Error("Unsupported chain driver", zap.String("network", name), zap.Error(err))
			return nil, err
		}
		result.byNetwork[name] = chainDriver
	}
	if len(result.byNetwork) == 0 {
		return nil, merrors.InvalidArgument("driver registry: no supported networks configured")
	}
	logger.Info("Chain drivers configured", zap.Int("count", len(result.byNetwork)))
	return result, nil
}

// Driver resolves a driver for the provided network key.
func (r *Registry) Driver(network string) (driver.Driver, error) {
	if r == nil || len(r.byNetwork) == 0 {
		return nil, merrors.Internal("driver registry is not configured")
	}
	key := strings.ToLower(strings.TrimSpace(network))
	if key == "" {
		return nil, merrors.InvalidArgument("network is required")
	}
	chainDriver, ok := r.byNetwork[key]
	if !ok {
		return nil, merrors.InvalidArgument(fmt.Sprintf("unsupported chain network %s", key))
	}
	return chainDriver, nil
}

func resolveDriver(logger mlogger.Logger, network string) (driver.Driver, error) {
	switch {
	case strings.HasPrefix(network, "tron"):
		return tron.New(logger), nil
	default:
		return nil, merrors.InvalidArgument("tron gateway only supports tron networks, got " + network)
	}
}
