package routers

import (
	"testing"
)

var testRoutersList = RoutersList{
	{
		ID:              "router1",
		DisplayName:     "DevelopersRouter",
		Description:     "First router",
		CreatedAt:       "2023-01-01",
		AccessGroupID:   "group1",
		AccessGroupName: "Developers",
		Enabled:         true,
		GatewayPorts: []GatewayPort{
			{
				ID:                "gateway1",
				Description:       "Gateway port 1",
				SNATEnabled:       true,
				ExternalL4PortMin: 1000,
				ExternalL4PortMax: 2000,
				CreatedAt:         "2023-01-01",
				UpdatedAt:         "2023-01-01",
				VersionID:         1,
				ExternalNetworkPort: ExternalNetworkPort{
					IPv4: "192.168.1.1",
					IPv6: "2001:db8::1",
				},
			},
		},
		Policies: []Policy{
			{
				ID:          "policy1",
				DisplayName: "Policy1",
				Action:      "allow",
				Priority:    1,
				Enabled:     true,
			},
		},
		Ports: []Port{
			{
				ID:          "port1",
				Description: "Port 1",
				Enabled:     true,
				IPv4Address: "10.0.0.1",
			},
		},
		Status: Status{
			Common: "active",
		},
		VersionID: 1,
	},
	{
		ID:              "router2",
		DisplayName:     "AdminsRouter",
		Description:     "Second router",
		CreatedAt:       "2023-01-02",
		AccessGroupID:   "group2",
		AccessGroupName: "Admins",
		Enabled:         true,
		GatewayPorts: []GatewayPort{
			{
				ID:                "gateway2",
				Description:       "Gateway port 2",
				SNATEnabled:       false,
				ExternalL4PortMin: 3000,
				ExternalL4PortMax: 4000,
				CreatedAt:         "2023-01-02",
				UpdatedAt:         "2023-01-02",
				VersionID:         1,
				ExternalNetworkPort: ExternalNetworkPort{
					IPv4: "192.168.1.2",
					IPv6: "2001:db8::2",
				},
			},
		},
		Policies: []Policy{
			{
				ID:          "policy2",
				DisplayName: "Policy2",
				Action:      "deny",
				Priority:    2,
				Enabled:     true,
			},
		},
		Ports: []Port{
			{
				ID:          "port2",
				Description: "Port 2",
				Enabled:     true,
				IPv4Address: "10.0.0.2",
			},
		},
		Status: Status{
			Common: "active",
		},
		VersionID: 2,
	},
	{
		ID:              "router3",
		DisplayName:     "UsersRouter",
		Description:     "Third router",
		CreatedAt:       "2023-01-03",
		AccessGroupID:   "group3",
		AccessGroupName: "Users",
		Enabled:         false,
		GatewayPorts: []GatewayPort{
			{
				ID:                "gateway3",
				Description:       "Gateway port 3",
				SNATEnabled:       true,
				ExternalL4PortMin: 5000,
				ExternalL4PortMax: 6000,
				CreatedAt:         "2023-01-03",
				UpdatedAt:         "2023-01-03",
				VersionID:         1,
				ExternalNetworkPort: ExternalNetworkPort{
					IPv4: "192.168.1.3",
					IPv6: "2001:db8::3",
				},
			},
		},
		Policies: []Policy{
			{
				ID:          "policy3",
				DisplayName: "Policy3",
				Action:      "allow",
				Priority:    3,
				Enabled:     false,
			},
		},
		Ports: []Port{
			{
				ID:          "port3",
				Description: "Port 3",
				Enabled:     false,
				IPv4Address: "10.0.0.3",
			},
		},
		Status: Status{
			Common: "inactive",
		},
		VersionID: 3,
	},
}

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

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

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

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

func TestFilterFunc(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		return rm.Description == "Second router"
	})

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

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

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

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

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

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

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

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

func TestFilterByEnabledStatus(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		return rm.Enabled
	})

	if len(actual) != 2 {
		t.Fatal("Expected 2 enabled routers, found:", len(actual))
	}
}

func TestFilterByAccessGroup(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		return rm.AccessGroupName == "Developers"
	})

	if len(actual) != 1 || actual[0].ID != "router1" {
		t.Fatal("Expected 1 router with Developers access group, found:", len(actual))
	}
}

func TestFilterByPolicyAction(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		for _, policy := range rm.Policies {
			if policy.Action == "deny" {
				return true
			}
		}
		return false
	})

	if len(actual) != 1 || actual[0].ID != "router2" {
		t.Fatal("Expected 1 router with deny policy, found:", len(actual))
	}
}

func TestFilterByGatewayPortRange(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		for _, gateway := range rm.GatewayPorts {
			if gateway.ExternalL4PortMin >= 3000 && gateway.ExternalL4PortMax <= 4000 {
				return true
			}
		}
		return false
	})

	if len(actual) != 1 || actual[0].ID != "router2" {
		t.Fatal("Expected 1 router with gateway port range 3000-4000, found:", len(actual))
	}
}

func TestFilterBySNATEnabled(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		for _, gateway := range rm.GatewayPorts {
			if gateway.SNATEnabled {
				return true
			}
		}
		return false
	})

	if len(actual) != 2 {
		t.Fatal("Expected 2 routers with SNAT enabled, found:", len(actual))
	}
}

func TestFilterByStatus(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		return rm.Status.Common == "inactive"
	})

	if len(actual) != 1 || actual[0].ID != "router3" {
		t.Fatal("Expected 1 router with inactive status, found:", len(actual))
	}
}

func TestFilterByPortEnabled(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		for _, port := range rm.Ports {
			if port.Enabled {
				return true
			}
		}
		return false
	})

	if len(actual) != 2 {
		t.Fatal("Expected 2 routers with enabled ports, found:", len(actual))
	}
}

func TestFilterByPolicyPriority(t *testing.T) {
	actual := testRoutersList.FilterFunc(func(rm RoutersModel) bool {
		for _, policy := range rm.Policies {
			if policy.Priority > 2 {
				return true
			}
		}
		return false
	})

	if len(actual) != 1 || actual[0].ID != "router3" {
		t.Fatal("Expected 1 router with policy priority > 2, found:", len(actual))
	}
}
