package resolver

import (
	"strings"

	"firewall_containers/network-go/config"
	"firewall_containers/network-go/logger"
)

// Resolver resolves names to IPs using the networks.json configuration
type Resolver struct {
	cfg     *config.NetworksConfig
	retries int
}

// NewResolver creates a new name resolver backed by the networks.json config
func NewResolver(cfg *config.NetworksConfig) *Resolver {
	r := &Resolver{
		cfg:     cfg,
		retries: 2,
	}
	if cfg != nil {
		logger.Debug("RESOLVER: created with %d IPs in config", len(cfg.IPs))
	} else {
		logger.Debug("RESOLVER: created with nil config")
	}
	return r
}

// SetConfig updates the config used for name resolution
func (r *Resolver) SetConfig(cfg *config.NetworksConfig) {
	r.cfg = cfg
	if cfg != nil {
		logger.Debug("RESOLVER: config updated with %d IPs", len(cfg.IPs))
	} else {
		logger.Debug("RESOLVER: config set to nil")
	}
}

// SetRetries sets the number of retries for resolution
func (r *Resolver) SetRetries(n int) {
	r.retries = n
	logger.Debug("RESOLVER: retries set to %d", n)
}

// Resolve resolves a name to one or more IP addresses
// It looks up the name in the networks.json config by container_name and selector fields
func (r *Resolver) Resolve(name string) []string {
	if r.cfg == nil {
		logger.Debug("RESOLVER: resolve(%q): config is nil", name)
		return nil
	}

	logger.Debug("RESOLVER: resolving %q", name)
	var ips []string

	// Look up by container_name and selector in the IPs section
	for _, ipCfg := range r.cfg.IPs {
		if ipCfg.ContainerName == name || ipCfg.Selector == name {
			logger.Debug("RESOLVER: exact match for %q: container=%s selector=%s -> IP=%s",
				name, ipCfg.ContainerName, ipCfg.Selector, ipCfg.IP)
			ips = append(ips, ipCfg.IP)
		}
	}

	// If no exact match, try prefix matching: extract the prefix before the first dash
	// and match any container/selector starting with that prefix.
	// This allows "wireguardproxy-client" to match "wireguardproxyclient" (after dash stripping)
	// or "app-1"/"app-2" to match "app-x".
	if len(ips) == 0 && strings.Contains(name, "-") {
		prefix := name[:strings.Index(name, "-")]
		logger.Debug("RESOLVER: prefix matching %q with prefix %q", name, prefix)
		for _, ipCfg := range r.cfg.IPs {
			if strings.HasPrefix(ipCfg.ContainerName, prefix) || strings.HasPrefix(ipCfg.Selector, prefix) {
				logger.Debug("RESOLVER: prefix match for %q: %s -> IP=%s", prefix, ipCfg.ContainerName, ipCfg.IP)
				ips = append(ips, ipCfg.IP)
			}
		}
	}

	if len(ips) == 0 {
		logger.Warn("RESOLVER: no IP found for %q in networks.json config", name)
	} else {
		logger.Info("RESOLVER: %q resolved to %v", name, ips)
	}

	return ips
}