package defsecpolicies

import (
	"testing"
)

var testSecurityPolicies = SecurityPoliciesList{
	Policies: []SecurityPolicy{
		{
			ID:                     "policy1",
			DisplayName:            "DevelopersPolicy",
			Description:            "First policy",
			CreatedAt:              "2023-01-01T00:00:00Z",
			UpdatedAt:              "2023-01-01T01:00:00Z",
			AccessGroupID:          "group1",
			DefaultACLDrop:         "DROP",
			DefaultOpenSessionDrop: true,
			SecurityRules: []SecurityRule{
				{
					ID:               "rule1",
					DisplayName:      "DevRule1",
					Action:           "ALLOW",
					Direction:        "INGRESS",
					Enabled:          true,
					Priority:         100,
					SecurityPolicyID: "policy1",
					VersionID:        1,
				},
			},
			Status: Status{
				Common: "ACTIVE",
				Hypervisors: []HypervisorStatus{
					{
						Name:             "hv1",
						DisplayName:      "Hypervisor1",
						Status:           "SYNCED",
						HypervisorStatus: "HEALTHY",
						SyncedAt:         "2023-01-01T01:00:00Z",
					},
				},
			},
			VersionID: 1,
		},
		{
			ID:                     "policy2",
			DisplayName:            "AdminsPolicy",
			Description:            "Second policy",
			CreatedAt:              "2023-01-02T00:00:00Z",
			UpdatedAt:              "2023-01-02T01:00:00Z",
			AccessGroupID:          "group2",
			DefaultACLDrop:         "REJECT",
			DefaultOpenSessionDrop: false,
			SecurityRules: []SecurityRule{
				{
					ID:               "rule2",
					DisplayName:      "AdminRule1",
					Action:           "DENY",
					Direction:        "EGRESS",
					Enabled:          true,
					Priority:         50,
					SecurityPolicyID: "policy2",
					VersionID:        1,
				},
			},
			Status: Status{
				Common: "ACTIVE",
				Hypervisors: []HypervisorStatus{
					{
						Name:             "hv2",
						DisplayName:      "Hypervisor2",
						Status:           "SYNCED",
						HypervisorStatus: "HEALTHY",
						SyncedAt:         "2023-01-02T01:00:00Z",
					},
				},
			},
			VersionID: 2,
		},
		{
			ID:                     "policy3",
			DisplayName:            "UsersPolicy",
			Description:            "Third policy",
			CreatedAt:              "2023-01-03T00:00:00Z",
			UpdatedAt:              "2023-01-03T01:00:00Z",
			AccessGroupID:          "group3",
			DefaultACLDrop:         "DROP",
			DefaultOpenSessionDrop: true,
			SecurityRules: []SecurityRule{
				{
					ID:               "rule3",
					DisplayName:      "UserRule1",
					Action:           "ALLOW",
					Direction:        "INGRESS",
					Enabled:          false,
					Priority:         200,
					SecurityPolicyID: "policy3",
					VersionID:        1,
				},
			},
			Status: Status{
				Common: "PENDING",
				Hypervisors: []HypervisorStatus{
					{
						Name:             "hv3",
						DisplayName:      "Hypervisor3",
						Status:           "SYNCING",
						HypervisorStatus: "HEALTHY",
						SyncedAt:         "2023-01-03T01:00:00Z",
					},
				},
			},
			VersionID: 3,
		},
	},
}

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

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

func TestFilterByDisplayName(t *testing.T) {
	actual := testSecurityPolicies.FilterByName("UsersPolicy").FindOne()

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

func TestFilterFunc(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		return sp.Description == "Second policy"
	})

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

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

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

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

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

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

func TestFilterByDisplayNameNotFound(t *testing.T) {
	actual := testSecurityPolicies.FilterByName("Nonexistent Policy")

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

func TestFilterByDefaultACLDrop(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		return sp.DefaultACLDrop == "DROP"
	})

	if len(actual.Policies) != 2 {
		t.Fatal("Expected 2 policies with DROP default ACL, found:", len(actual.Policies))
	}
}

func TestFilterByDefaultOpenSessionDrop(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		return sp.DefaultOpenSessionDrop == true
	})

	if len(actual.Policies) != 2 {
		t.Fatal("Expected 2 policies with default open session drop enabled, found:", len(actual.Policies))
	}
}

func TestFilterByStatus(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		return sp.Status.Common == "ACTIVE"
	})

	if len(actual.Policies) != 2 {
		t.Fatal("Expected 2 policies with ACTIVE status, found:", len(actual.Policies))
	}
}

func TestFilterByAccessGroupID(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		return sp.AccessGroupID == "group1"
	})

	if len(actual.Policies) != 1 || actual.Policies[0].ID != "policy1" {
		t.Fatal("Expected 1 policy with access group ID 'group1', found:", len(actual.Policies))
	}
}

func TestFilterByRuleAction(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		for _, rule := range sp.SecurityRules {
			if rule.Action == "ALLOW" {
				return true
			}
		}
		return false
	})

	if len(actual.Policies) != 2 {
		t.Fatal("Expected 2 policies with ALLOW rules, found:", len(actual.Policies))
	}
}

func TestFilterByRuleDirection(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		for _, rule := range sp.SecurityRules {
			if rule.Direction == "INGRESS" {
				return true
			}
		}
		return false
	})

	if len(actual.Policies) != 2 {
		t.Fatal("Expected 2 policies with INGRESS rules, found:", len(actual.Policies))
	}
}

func TestFilterByRuleEnabled(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		for _, rule := range sp.SecurityRules {
			if rule.Enabled {
				return true
			}
		}
		return false
	})

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

func TestFilterByVersionID(t *testing.T) {
	actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
		return sp.VersionID > 1
	})

	if len(actual.Policies) != 2 {
		t.Fatal("Expected 2 policies with version ID > 1, found:", len(actual.Policies))
	}
}
