package ruleset

import (
	"net"
	"testing"

	"git.difuse.io/Difuse/Mellaris/analyzer"
)

func TestAction_String(t *testing.T) {
	tests := []struct {
		action Action
		want   string
	}{
		{ActionMaybe, "maybe"},
		{ActionAllow, "allow"},
		{ActionBlock, "block"},
		{ActionDrop, "drop"},
		{ActionModify, "modify"},
		{Action(99), "unknown"},
	}

	for _, tt := range tests {
		t.Run(tt.want, func(t *testing.T) {
			if got := tt.action.String(); got != tt.want {
				t.Errorf("Action.String() = %q, want %q", got, tt.want)
			}
		})
	}
}

func TestProtocol_String(t *testing.T) {
	tests := []struct {
		protocol Protocol
		want     string
	}{
		{ProtocolTCP, "tcp"},
		{ProtocolUDP, "udp"},
		{Protocol(99), "unknown"},
	}

	for _, tt := range tests {
		t.Run(tt.want, func(t *testing.T) {
			if got := tt.protocol.String(); got != tt.want {
				t.Errorf("Protocol.String() = %q, want %q", got, tt.protocol)
			}
		})
	}
}

func TestProtocol_Constants(t *testing.T) {
	if ProtocolTCP != 0 {
		t.Errorf("ProtocolTCP = %d, want 0", ProtocolTCP)
	}
	if ProtocolUDP != 1 {
		t.Errorf("ProtocolUDP = %d, want 1", ProtocolUDP)
	}
}

func TestAction_Constants(t *testing.T) {
	if ActionMaybe != 0 {
		t.Errorf("ActionMaybe = %d, want 0", ActionMaybe)
	}
	if ActionAllow != 1 {
		t.Errorf("ActionAllow = %d, want 1", ActionAllow)
	}
	if ActionBlock != 2 {
		t.Errorf("ActionBlock = %d, want 2", ActionBlock)
	}
}

func TestStreamInfo_SrcString(t *testing.T) {
	info := StreamInfo{
		SrcIP:   net.ParseIP("192.168.1.1"),
		SrcPort: 8080,
	}
	want := "192.168.1.1:8080"
	if got := info.SrcString(); got != want {
		t.Errorf("SrcString() = %q, want %q", got, want)
	}
}

func TestStreamInfo_DstString(t *testing.T) {
	info := StreamInfo{
		DstIP:   net.ParseIP("10.0.0.1"),
		DstPort: 443,
	}
	want := "10.0.0.1:443"
	if got := info.DstString(); got != want {
		t.Errorf("DstString() = %q, want %q", got, want)
	}
}

func TestStreamInfo_SrcString_IPv6(t *testing.T) {
	info := StreamInfo{
		SrcIP:   net.ParseIP("::1"),
		SrcPort: 53,
	}
	want := "[::1]:53"
	if got := info.SrcString(); got != want {
		t.Errorf("SrcString() = %q, want %q", got, want)
	}
}

func TestMatchResult_ZeroValue(t *testing.T) {
	var mr MatchResult
	if mr.Action != ActionMaybe {
		t.Errorf("zero MatchResult.Action = %v, want ActionMaybe (0)", mr.Action)
	}
}

func TestStreamInfo_PropsInitialization(t *testing.T) {
	info := StreamInfo{
		Props: analyzer.CombinedPropMap{
			"tls": analyzer.PropMap{"sni": "example.com"},
		},
	}
	if info.Props.Get("tls", "sni") != "example.com" {
		t.Error("StreamInfo.Props not properly initialized")
	}
}
