package adrspools

import (
	"testing"
)

var testAddressPools = AddressPoolsList{
	Pools: []NetworkAddressPool{
		{
			ID:              "pool1",
			Name:            "DevelopersPool",
			Description:     "First pool",
			CreatedAt:       "2023-01-01",
			AccessGroupID:   "group1",
			AccessGroupName: "Developers",
			NetAddressType:  "IPv4",
			NetAddresses: []NetworkAddress{
				{
					ID:               "addr1",
					IPAddr:           "192.168.1.1",
					NetAddressType:   "IPv4",
					NetAddressPoolID: "pool1",
				},
			},
			PoolCounters: PoolCounters{
				SecurityRules: 5,
			},
			VersionID: 1,
		},
		{
			ID:              "pool2",
			Name:            "AdminsPool",
			Description:     "Second pool",
			CreatedAt:       "2023-01-02",
			AccessGroupID:   "group2",
			AccessGroupName: "Admins",
			NetAddressType:  "IPv4",
			NetAddresses: []NetworkAddress{
				{
					ID:               "addr2",
					IPAddr:           "192.168.1.2",
					NetAddressType:   "IPv4",
					NetAddressPoolID: "pool2",
				},
			},
			PoolCounters: PoolCounters{
				SecurityRules: 3,
			},
			VersionID: 2,
		},
		{
			ID:              "pool3",
			Name:            "UsersPool",
			Description:     "Third pool",
			CreatedAt:       "2023-01-03",
			AccessGroupID:   "group3",
			AccessGroupName: "Users",
			NetAddressType:  "IPv6",
			NetAddresses: []NetworkAddress{
				{
					ID:               "addr3",
					IPAddr:           "2001:db8::1",
					NetAddressType:   "IPv6",
					NetAddressPoolID: "pool3",
				},
			},
			PoolCounters: PoolCounters{
				SecurityRules: 7,
			},
			VersionID: 3,
		},
	},
}

func TestFilterByID(t *testing.T) {
	actual := testAddressPools.FilterByID("pool2").FindOne()

	if actual.ID != "pool2" {
		t.Fatal("actual:", actual.ID, "> expected: pool2")
	}
}

func TestFilterByName(t *testing.T) {
	actual := testAddressPools.FilterByName("UsersPool").FindOne()

	if actual.Name != "UsersPool" {
		t.Fatal("actual:", actual.Name, ">> expected: UsersPool")
	}
}

func TestFilterFunc(t *testing.T) {
	actual := testAddressPools.FilterFunc(func(ap NetworkAddressPool) bool {
		return ap.Description == "Second pool"
	})

	if len(actual.Pools) != 1 || actual.Pools[0].ID != "pool2" {
		t.Fatal("Expected 1 pool with description 'Second pool', found:", len(actual.Pools))
	}
}

func TestFindOneWithResults(t *testing.T) {
	result := testAddressPools.FilterByID("pool1").FindOne()
	if result.ID != "pool1" {
		t.Fatal("Expected pool1, got:", result.ID)
	}
}

func TestFindOneEmpty(t *testing.T) {
	emptyList := AddressPoolsList{}
	result := emptyList.FindOne()

	if result.ID != "" || result.Name != "" {
		t.Fatal("Expected empty NetworkAddressPool, got:", result)
	}
}

func TestFilterByIDNotFound(t *testing.T) {
	actual := testAddressPools.FilterByID("nonexistent")

	if len(actual.Pools) != 0 {
		t.Fatal("Expected 0 pools, found:", len(actual.Pools))
	}
}

func TestFilterByNameNotFound(t *testing.T) {
	actual := testAddressPools.FilterByName("Nonexistent Pool")

	if len(actual.Pools) != 0 {
		t.Fatal("Expected 0 pools, found:", len(actual.Pools))
	}
}

func TestFilterByNetAddressType(t *testing.T) {
	actual := testAddressPools.FilterFunc(func(ap NetworkAddressPool) bool {
		return ap.NetAddressType == "IPv6"
	})

	if len(actual.Pools) != 1 || actual.Pools[0].ID != "pool3" {
		t.Fatal("Expected 1 pool with IPv6 type, found:", len(actual.Pools))
	}
}

func TestFilterBySecurityRulesCount(t *testing.T) {
	actual := testAddressPools.FilterFunc(func(ap NetworkAddressPool) bool {
		return ap.PoolCounters.SecurityRules > 4
	})

	if len(actual.Pools) != 2 {
		t.Fatal("Expected 2 pools with more than 4 security rules, found:", len(actual.Pools))
	}
}
