package resolver

import (
	"testing"

	"firewall_containers/network-go/config"
)

func makeTestConfig() *config.NetworksConfig {
	return &config.NetworksConfig{
		Networks: map[string]config.NetworkConfig{
			"test-net": {NetworkName: "test-net", Subnet: "172.18.103.0/24", Gateway: "172.18.103.1"},
		},
		IPs: map[string]config.IPConfig{
			"172.18.103.2": {IP: "172.18.103.2", ContainerName: "smarthostloadbalancer", Selector: "smarthostloadbalancer", ServiceName: "smarthost-proxy"},
			"172.18.104.2": {IP: "172.18.104.2", ContainerName: "smarthostbackend-1", Selector: "smarthostbackend-1", ServiceName: "smarthost-proxy"},
		},
		Policies: []config.PolicyConfig{},
	}
}

func TestResolveByContainerName(t *testing.T) {
	cfg := makeTestConfig()
	r := NewResolver(cfg)

	ips := r.Resolve("smarthostloadbalancer")
	if len(ips) != 1 {
		t.Fatalf("expected 1 IP, got %d", len(ips))
	}
	if ips[0] != "172.18.103.2" {
		t.Errorf("expected 172.18.103.2, got %s", ips[0])
	}
}

func TestResolveBySelector(t *testing.T) {
	cfg := makeTestConfig()
	r := NewResolver(cfg)

	ips := r.Resolve("smarthostbackend-1")
	if len(ips) != 1 {
		t.Fatalf("expected 1 IP, got %d", len(ips))
	}
	if ips[0] != "172.18.104.2" {
		t.Errorf("expected 172.18.104.2, got %s", ips[0])
	}
}

func TestResolveNotFound(t *testing.T) {
	cfg := makeTestConfig()
	r := NewResolver(cfg)

	ips := r.Resolve("nonexistent-container")
	if len(ips) != 0 {
		t.Errorf("expected 0 IPs, got %d", len(ips))
	}
}

func TestResolveNilConfig(t *testing.T) {
	r := NewResolver(nil)

	ips := r.Resolve("anything")
	if len(ips) != 0 {
		t.Errorf("expected 0 IPs with nil config, got %d", len(ips))
	}
}

func TestSetConfig(t *testing.T) {
	r := NewResolver(nil)

	// Initially nil config
	ips := r.Resolve("test")
	if len(ips) != 0 {
		t.Errorf("expected 0 IPs with nil config, got %d", len(ips))
	}

	// Update with valid config
	cfg := makeTestConfig()
	r.SetConfig(cfg)

	ips = r.Resolve("smarthostloadbalancer")
	if len(ips) != 1 {
		t.Fatalf("expected 1 IP after SetConfig, got %d", len(ips))
	}
	if ips[0] != "172.18.103.2" {
		t.Errorf("expected 172.18.103.2, got %s", ips[0])
	}
}

func TestResolveReproducible(t *testing.T) {
	cfg := makeTestConfig()
	r := NewResolver(cfg)

	ips1 := r.Resolve("smarthostloadbalancer")
	ips2 := r.Resolve("smarthostloadbalancer")

	if len(ips1) != len(ips2) {
		t.Errorf("reproducibility: result count mismatch %d vs %d", len(ips1), len(ips2))
	}
	if len(ips1) > 0 && ips1[0] != ips2[0] {
		t.Errorf("reproducibility: IP mismatch %s vs %s", ips1[0], ips2[0])
	}
}

func TestResolveMultipleMatch(t *testing.T) {
	cfg := &config.NetworksConfig{
		IPs: map[string]config.IPConfig{
			"10.0.0.1": {IP: "10.0.0.1", ContainerName: "app-1", Selector: "app-1"},
			"10.0.0.2": {IP: "10.0.0.2", ContainerName: "app-2", Selector: "app-2"},
		},
	}
	r := NewResolver(cfg)

	// "app-x" has a dash, so prefix "app" is extracted and matches both app-1 and app-2
	ips := r.Resolve("app-x")
	if len(ips) != 2 {
		t.Errorf("expected 2 IPs for prefix match, got %d", len(ips))
	}
}
