package parser

import (
	"eq2emu/internal/common"
	"testing"
)

func TestBasicParsing(t *testing.T) {
	pml := `<packet name="Test">
		<version number="1">
			<i32 name="player_id">
			<str16 name="player_name">
			<color name="skin_color">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["Test"]
	if packet == nil {
		t.Fatal("Test packet not found")
	}

	// Check fields
	if len(packet.Fields) != 3 {
		t.Errorf("Expected 3 fields, got %d", len(packet.Fields))
	}

	if packet.Fields["player_id"].Type != common.TypeSInt32 {
		t.Error("player_id should be TypeSInt32")
	}

	if packet.Fields["player_name"].Type != common.TypeString16 {
		t.Error("player_name should be TypeString16")
	}

	if packet.Fields["skin_color"].Type != common.TypeColor {
		t.Error("skin_color should be TypeColor")
	}

	// Check order
	order := packet.Orders[1]
	expected := []string{"player_id", "player_name", "skin_color"}
	if !equalSlices(order, expected) {
		t.Errorf("Expected order %v, got %v", expected, order)
	}
}

func TestFloat64Support(t *testing.T) {
	pml := `<packet name="FloatTest">
		<version number="1">
			<f32 name="position_x">
			<f64 name="precise_value">
			<double name="legacy_double">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["FloatTest"]
	if packet.Fields["position_x"].Type != common.TypeFloat {
		t.Error("position_x should be TypeFloat")
	}
	if packet.Fields["precise_value"].Type != common.TypeDouble {
		t.Error("precise_value should be TypeDouble")
	}
	if packet.Fields["legacy_double"].Type != common.TypeDouble {
		t.Error("legacy_double should be TypeDouble")
	}
}

func TestOversizedFields(t *testing.T) {
	pml := `<packet name="OversizedTest">
		<version number="1">
			<i8 name="small_count">
			<i16 name="num_words" oversized="255">
			<i32 name="large_value" oversized="65535">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["OversizedTest"]
	if packet.Fields["small_count"].Oversized != 0 {
		t.Error("small_count should not be oversized")
	}
	if packet.Fields["num_words"].Oversized != 255 {
		t.Errorf("num_words oversized should be 255, got %d", packet.Fields["num_words"].Oversized)
	}
	if packet.Fields["large_value"].Oversized != 65535 {
		t.Errorf("large_value oversized should be 65535, got %d", packet.Fields["large_value"].Oversized)
	}
}

func TestType2Support(t *testing.T) {
	pml := `<packet name="Type2Test">
		<version number="1">
			<i8 name="stat_type">
			<i32 name="stat_value" type2="f32" type2_if="stat_type!=6">
			<i16 name="another_field" type2="i32">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["Type2Test"]
	statValue := packet.Fields["stat_value"]
	if statValue.Type != common.TypeSInt32 {
		t.Error("stat_value primary type should be TypeSInt32")
	}
	if statValue.Type2 != common.TypeFloat {
		t.Error("stat_value type2 should be TypeFloat")
	}
	if statValue.Type2Cond != "stat_type!=6" {
		t.Errorf("Expected type2_if 'stat_type!=6', got '%s'", statValue.Type2Cond)
	}

	anotherField := packet.Fields["another_field"]
	if anotherField.Type2 != common.TypeSInt32 {
		t.Error("another_field type2 should be TypeSInt32")
	}
	if anotherField.Type2Cond != "" {
		t.Error("another_field should have empty type2_if")
	}
}

func TestAdvancedFieldAttributes(t *testing.T) {
	pml := `<packet name="AttributeTest">
		<version number="1">
			<i8 name="data_array" size="10" default="5">
			<str16 name="optional_text" if="var:has_text" optional="true">
			<i32 name="hidden_field" add_to_struct="false" add_type="i16">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["AttributeTest"]

	dataArray := packet.Fields["data_array"]
	if dataArray.Length != 10 {
		t.Errorf("Expected size 10, got %d", dataArray.Length)
	}
	if dataArray.DefaultValue != 5 {
		t.Errorf("Expected default 5, got %d", dataArray.DefaultValue)
	}

	optionalText := packet.Fields["optional_text"]
	if optionalText.Condition != "var:has_text" {
		t.Errorf("Expected condition 'var:has_text', got '%s'", optionalText.Condition)
	}
	if !optionalText.Optional {
		t.Error("optional_text should be optional")
	}

	hiddenField := packet.Fields["hidden_field"]
	if hiddenField.AddToStruct {
		t.Error("hidden_field should not be added to struct")
	}
	if hiddenField.AddType != common.TypeSInt16 {
		t.Error("hidden_field add_type should be TypeSInt16")
	}
}

func TestArrayMaxSize(t *testing.T) {
	pml := `<packet name="ArrayMaxTest">
		<version number="1">
			<i8 name="item_count">
			<array name="items" count="var:item_count" max_size="100">
				<i32 name="item_id">
			</array>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["ArrayMaxTest"]
	itemsField := packet.Fields["items"]

	if itemsField.MaxArraySize != 100 {
		t.Errorf("Expected max_size 100, got %d", itemsField.MaxArraySize)
	}
}

func TestArrayOptionalAttributes(t *testing.T) {
	pml := `<packet name="ArrayOptionalTest">
		<version number="1">
			<i8 name="count">
			<array name="optional_items" count="var:count" optional="true" add_to_struct="false">
				<i32 name="id">
			</array>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["ArrayOptionalTest"]
	itemsField := packet.Fields["optional_items"]

	if !itemsField.Optional {
		t.Error("optional_items should be optional")
	}
	if itemsField.AddToStruct {
		t.Error("optional_items should not be added to struct")
	}
}

func TestMultipleVersions(t *testing.T) {
	pml := `<packet name="MultiVersion">
		<version number="1">
			<i32 name="id">
			<str16 name="name">
		</version>
		<version number="562">
			<i32 name="id">
			<str16 name="name">
			<color name="color">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["MultiVersion"]
	if packet == nil {
		t.Fatal("MultiVersion packet not found")
	}

	// Check both versions exist
	if len(packet.Orders) != 2 {
		t.Errorf("Expected 2 versions, got %d", len(packet.Orders))
	}

	v1Order := packet.Orders[1]
	v562Order := packet.Orders[562]

	if len(v1Order) != 2 {
		t.Errorf("Version 1 should have 2 fields, got %d", len(v1Order))
	}

	if len(v562Order) != 3 {
		t.Errorf("Version 562 should have 3 fields, got %d", len(v562Order))
	}
}

func TestArrayParsing(t *testing.T) {
	pml := `<packet name="ArrayTest">
		<version number="1">
			<i8 name="item_count">
			<array name="items" count="var:item_count">
				<i32 name="item_id">
				<str16 name="item_name">
			</array>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["ArrayTest"]
	itemsField := packet.Fields["items"]

	if itemsField.Type != common.TypeArray {
		t.Error("items should be TypeArray")
	}

	if itemsField.Condition != "var:item_count" {
		t.Errorf("Expected condition 'var:item_count', got '%s'", itemsField.Condition)
	}

	if itemsField.SubDef == nil {
		t.Fatal("SubDef should not be nil")
	}

	// Check substruct fields
	if len(itemsField.SubDef.Fields) != 2 {
		t.Errorf("Expected 2 substruct fields, got %d", len(itemsField.SubDef.Fields))
	}

	if itemsField.SubDef.Fields["item_id"].Type != common.TypeSInt32 {
		t.Error("item_id should be TypeSInt32")
	}
}

func TestConditionalParsing(t *testing.T) {
	pml := `<packet name="ConditionalTest">
		<version number="1">
			<i32 name="player_id">
			<str16 name="guild_name" if="flag:has_guild">
			<i8 name="enhancement" if="item_type!=0">
			<color name="aura" if="special_flags&0x01">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["ConditionalTest"]

	if packet.Fields["guild_name"].Condition != "flag:has_guild" {
		t.Errorf("guild_name condition wrong: %s", packet.Fields["guild_name"].Condition)
	}

	if packet.Fields["enhancement"].Condition != "item_type!=0" {
		t.Errorf("enhancement condition wrong: %s", packet.Fields["enhancement"].Condition)
	}

	if packet.Fields["aura"].Condition != "special_flags&0x01" {
		t.Errorf("aura condition wrong: %s", packet.Fields["aura"].Condition)
	}
}

func TestCommaFieldNames(t *testing.T) {
	pml := `<packet name="CommaTest">
		<version number="1">
			<i32 name="player_id,account_id">
			<f32 name="pos_x,pos_y,pos_z">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["CommaTest"]

	expectedFields := []string{"player_id", "account_id", "pos_x", "pos_y", "pos_z"}
	if len(packet.Fields) != len(expectedFields) {
		t.Errorf("Expected %d fields, got %d", len(expectedFields), len(packet.Fields))
	}

	for _, field := range expectedFields {
		if _, exists := packet.Fields[field]; !exists {
			t.Errorf("Field %s not found", field)
		}
	}
}

func TestSubstructReference(t *testing.T) {
	pml := `<substruct name="ItemInfo">
		<i32 name="item_id">
		<str16 name="item_name">
	</substruct>

	<packet name="SubstructTest">
		<version number="1">
			<i8 name="count">
			<array name="items" count="var:count" substruct="ItemInfo">
		</version>
	</packet>`

	parser := NewParser(pml)
	packets, err := parser.Parse()
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["SubstructTest"]
	itemsField := packet.Fields["items"]

	if itemsField.SubDef == nil {
		t.Fatal("SubDef should not be nil for referenced substruct")
	}

	if len(itemsField.SubDef.Fields) != 2 {
		t.Errorf("Expected 2 substruct fields, got %d", len(itemsField.SubDef.Fields))
	}
}

func TestFieldAttributes(t *testing.T) {
	pml := `<packet name="AttributeTest">
		<version number="1">
			<i8 name="data_array" size="10">
			<str16 name="optional_text" if="var:has_text">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["AttributeTest"]

	if packet.Fields["data_array"].Length != 10 {
		t.Errorf("Expected size 10, got %d", packet.Fields["data_array"].Length)
	}

	if packet.Fields["optional_text"].Condition != "var:has_text" {
		t.Errorf("Expected condition 'var:has_text', got '%s'", packet.Fields["optional_text"].Condition)
	}
}

func TestComments(t *testing.T) {
	pml := `<!-- This is a comment -->
	<packet name="CommentTest">
		<!-- Another comment -->
		<version number="1">
			<i32 name="id"> <!-- Inline comment -->
			<str16 name="name">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["CommentTest"]
	if len(packet.Fields) != 2 {
		t.Errorf("Comments should not affect parsing, expected 2 fields, got %d", len(packet.Fields))
	}
}

func TestBinaryParsingFloat64(t *testing.T) {
	// Test binary parsing with float64
	pml := `<packet name="BinaryFloat64">
		<version number="1">
			<f64 name="precise_value">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	// Create test data: 8 bytes representing float64 value 123.456
	testData := []byte{0x77, 0xbe, 0x9f, 0x1a, 0x2f, 0xdd, 0x5e, 0x40} // 123.456 in little-endian

	result, err := packets["BinaryFloat64"].Parse(testData, 1, 0)
	if err != nil {
		t.Fatalf("Binary parse failed: %v", err)
	}

	if val, ok := result["precise_value"].(float64); !ok {
		t.Error("precise_value should be float64")
	} else if val < 123.0 || val > 124.0 { // Rough check
		t.Errorf("Expected value around 123.456, got %f", val)
	}
}

func TestBinaryParsingOversized(t *testing.T) {
	// Test oversized field parsing
	pml := `<packet name="BinaryOversized">
		<version number="1">
			<i16 name="normal_value">
			<i16 name="oversized_value" oversized="255">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	// Test data: normal 16-bit value (100), then oversized marker (255) + 16-bit value (1000)
	testData := []byte{0x64, 0x00, 0xff, 0xe8, 0x03} // 100, 255, 1000

	result, err := packets["BinaryOversized"].Parse(testData, 1, 0)
	if err != nil {
		t.Fatalf("Binary parse failed: %v", err)
	}

	if val := result["normal_value"].(int16); val != 100 {
		t.Errorf("Expected normal_value 100, got %d", val)
	}

	if val := result["oversized_value"].(int16); val != 1000 {
		t.Errorf("Expected oversized_value 1000, got %d", val)
	}
}

func TestBinaryParsingType2(t *testing.T) {
	// Test type2 switching in binary parsing
	pml := `<packet name="BinaryType2">
		<version number="1">
			<i8 name="stat_type">
			<i32 name="stat_value" type2="f32" type2_if="stat_type==6">
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	// Test with stat_type = 6 (should use float)
	testData1 := []byte{0x06, 0x00, 0x00, 0x20, 0x41} // stat_type=6, float 10.0

	result1, err := packets["BinaryType2"].Parse(testData1, 1, 0)
	if err != nil {
		t.Fatalf("Binary parse failed: %v", err)
	}

	if statType := result1["stat_type"].(int8); statType != 6 {
		t.Errorf("Expected stat_type 6, got %d", statType)
	}

	// Note: The actual type switching logic depends on conditions.go implementation
	// This test verifies the parsing structure is correct
}

func TestBinaryParsingArrayMaxSize(t *testing.T) {
	// Test array max size limit
	pml := `<packet name="BinaryArrayMax">
		<version number="1">
			<i8 name="item_count">
			<array name="items" count="var:item_count" max_size="2">
				<i16 name="item_id">
			</array>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	// Test data: count=5, but max_size=2 should limit to 2 items
	testData := []byte{0x05, 0x01, 0x00, 0x02, 0x00} // count=5, item1=1, item2=2

	result, err := packets["BinaryArrayMax"].Parse(testData, 1, 0)
	if err != nil {
		t.Fatalf("Binary parse failed: %v", err)
	}

	items := result["items"].([]map[string]any)
	if len(items) != 2 {
		t.Errorf("Expected 2 items due to max_size, got %d", len(items))
	}
}

func TestArrayIndexConditions(t *testing.T) {
	// Test array index substitution in conditions
	pml := `<packet name="ArrayConditionTest">
		<version number="1">
			<i8 name="stat_count">
			<array name="stats" count="var:stat_count">
				<i8 name="stat_type">
				<i32 name="base_value">
				<i32 name="modified_value" if="stat_type_%i>=1&stat_type_%i<=5">
				<f32 name="percentage" if="stat_type_%i==6">
				<str16 name="description" if="!var:stat_type_%i">
			</array>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["ArrayConditionTest"]

	// Verify fields were parsed correctly
	statsField := packet.Fields["stats"]
	if statsField.Type != common.TypeArray {
		t.Error("stats should be TypeArray")
	}

	if statsField.SubDef == nil {
		t.Fatal("SubDef should not be nil")
	}

	// Check that conditions were preserved
	modifiedValue := statsField.SubDef.Fields["modified_value"]
	if modifiedValue.Condition != "stat_type_%i>=1&stat_type_%i<=5" {
		t.Errorf("Expected 'stat_type_%%i>=1&stat_type_%%i<=5', got '%s'", modifiedValue.Condition)
	}

	percentage := statsField.SubDef.Fields["percentage"]
	if percentage.Condition != "stat_type_%i==6" {
		t.Errorf("Expected 'stat_type_%%i==6', got '%s'", percentage.Condition)
	}

	description := statsField.SubDef.Fields["description"]
	if description.Condition != "!var:stat_type_%i" {
		t.Errorf("Expected '!var:stat_type_%%i', got '%s'", description.Condition)
	}
}

func TestArrayIndexBinaryParsing(t *testing.T) {
	// Test that array index conditions work during binary parsing
	pml := `<packet name="ArrayConditionBinary">
		<version number="1">
			<i8 name="stat_count">
			<array name="stats" count="var:stat_count">
				<i8 name="stat_type">
				<i32 name="base_value">
				<f32 name="percentage" if="stat_type_%i==6">
			</array>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	// Test data: 2 stats, first with type=5, second with type=6
	// stat_count=2, stat1: type=5, base=100, stat2: type=6, base=200, percentage=1.5
	testData := []byte{
		0x02,                         // stat_count = 2
		0x05, 0x64, 0x00, 0x00, 0x00, // stat 1: type=5, base=100 (no percentage)
		0x06, 0xC8, 0x00, 0x00, 0x00, // stat 2: type=6, base=200
		0x00, 0x00, 0xC0, 0x3F, // percentage=1.5 (float32)
	}

	result, err := packets["ArrayConditionBinary"].Parse(testData, 1, 0)
	if err != nil {
		t.Fatalf("Binary parse failed: %v", err)
	}

	stats := result["stats"].([]map[string]any)
	if len(stats) != 2 {
		t.Fatalf("Expected 2 stats, got %d", len(stats))
	}

	// First stat (type=5) should not have percentage field
	stat1 := stats[0]
	if stat1["stat_type"].(int8) != 5 {
		t.Errorf("Expected stat_type 5, got %d", stat1["stat_type"])
	}
	if _, hasPercentage := stat1["percentage"]; hasPercentage {
		t.Error("Stat type 5 should not have percentage field")
	}

	// Second stat (type=6) should have percentage field
	stat2 := stats[1]
	if stat2["stat_type"].(int8) != 6 {
		t.Errorf("Expected stat_type 6, got %d", stat2["stat_type"])
	}
	if percentage, hasPercentage := stat2["percentage"]; !hasPercentage {
		t.Error("Stat type 6 should have percentage field")
	} else if percentage.(float32) < 1.4 || percentage.(float32) > 1.6 {
		t.Errorf("Expected percentage around 1.5, got %f", percentage)
	}
}

func TestComplexArrayConditions(t *testing.T) {
	// Test complex conditions with array indices
	pml := `<packet name="ComplexArrayTest">
		<version number="1">
			<i8 name="item_count">
			<array name="items" count="var:item_count">
				<i16 name="item_type">
				<i32 name="item_flags">
				<i8 name="enhancement" if="item_type_%i!=0&item_flags_%i&0x01">
				<color name="special_color" if="item_type_%i>=100,item_flags_%i&0x02">
			</array>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	packet := packets["ComplexArrayTest"]
	itemsField := packet.Fields["items"]

	enhancement := itemsField.SubDef.Fields["enhancement"]
	if enhancement.Condition != "item_type_%i!=0&item_flags_%i&0x01" {
		t.Errorf("Enhancement condition wrong: %s", enhancement.Condition)
	}

	specialColor := itemsField.SubDef.Fields["special_color"]
	if specialColor.Condition != "item_type_%i>=100,item_flags_%i&0x02" {
		t.Errorf("Special color condition wrong: %s", specialColor.Condition)
	}
}

func TestErrorHandling(t *testing.T) {
	testCases := []struct {
		name string
		pml  string
	}{
		{"Unclosed tag", "<packet name=\"Test\"><version number=\"1\"><i32 name=\"id\">"},
		{"Invalid XML", "<packet><version><i32></packet>"},
		{"Missing quotes", "<packet name=Test><version number=1></version></packet>"},
		{"Invalid oversized", "<packet name=\"Test\"><version number=\"1\"><i32 name=\"id\" oversized=\"abc\"></version></packet>"},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			_, err := Parse(tc.pml)
			if err == nil {
				t.Error("Expected error but got none")
			}
		})
	}
}

func TestTemplateDefinitionAndUsage(t *testing.T) {
	pml := `<!-- Define reusable templates -->
	<template name="position">
		<f32 name="x,y,z">
		<f32 name="heading">
	</template>

	<template name="appearance">
		<color name="skin_color,hair_color,eye_color">
		<str16 name="face_file,hair_file">
	</template>

	<!-- Use templates in packet -->
	<packet name="PlayerUpdate">
		<version number="1">
			<i32 name="player_id">
			<template use="position">
			<i8 name="level">
			<template use="appearance">
			<str16 name="guild_name" if="flag:has_guild">
		</version>
	</packet>

	<!-- Test template with group prefix -->
	<packet name="GroupedTemplate">
		<version number="1">
			<i32 name="entity_id">
			<group name="current">
				<template use="position">
			</group>
			<group name="target">
				<template use="position">
			</group>
		</version>
	</packet>`

	packets, err := Parse(pml)
	if err != nil {
		t.Fatalf("Parse failed: %v", err)
	}

	// Test basic template injection
	playerPacket := packets["PlayerUpdate"]
	if playerPacket == nil {
		t.Fatal("PlayerUpdate packet not found")
	}

	// Check that template fields were injected
	expectedFields := []string{"player_id", "x", "y", "z", "heading", "level", "skin_color", "hair_color", "eye_color", "face_file", "hair_file", "guild_name"}
	if len(playerPacket.Fields) != len(expectedFields) {
		t.Errorf("Expected %d fields, got %d", len(expectedFields), len(playerPacket.Fields))
	}

	// Verify specific template fields exist with correct types
	if playerPacket.Fields["x"].Type != common.TypeFloat {
		t.Error("x should be TypeFloat from position template")
	}
	if playerPacket.Fields["heading"].Type != common.TypeFloat {
		t.Error("heading should be TypeFloat from position template")
	}
	if playerPacket.Fields["skin_color"].Type != common.TypeColor {
		t.Error("skin_color should be TypeColor from appearance template")
	}
	if playerPacket.Fields["face_file"].Type != common.TypeString16 {
		t.Error("face_file should be TypeString16 from appearance template")
	}

	// Check field ordering preserves template injection points
	order := playerPacket.Orders[1]
	expectedOrder := []string{"player_id", "x", "y", "z", "heading", "level", "skin_color", "hair_color", "eye_color", "face_file", "hair_file", "guild_name"}
	if !equalSlices(order, expectedOrder) {
		t.Errorf("Expected order %v, got %v", expectedOrder, order)
	}

	// Test template with group prefixes
	groupedPacket := packets["GroupedTemplate"]
	if groupedPacket == nil {
		t.Fatal("GroupedTemplate packet not found")
	}

	// Check prefixed fields from templates
	if groupedPacket.Fields["current_x"].Type != common.TypeFloat {
		t.Error("current_x should exist from prefixed template")
	}
	if groupedPacket.Fields["target_heading"].Type != common.TypeFloat {
		t.Error("target_heading should exist from prefixed template")
	}

	// Verify grouped template field order
	groupedOrder := groupedPacket.Orders[1]
	expectedGroupedOrder := []string{"entity_id", "current_x", "current_y", "current_z", "current_heading", "target_x", "target_y", "target_z", "target_heading"}
	if !equalSlices(groupedOrder, expectedGroupedOrder) {
		t.Errorf("Expected grouped order %v, got %v", expectedGroupedOrder, groupedOrder)
	}
}

func BenchmarkSimplePacket(b *testing.B) {
	pml := `<packet name="Simple">
		<version number="1">
			<i32 name="id">
			<str16 name="name">
			<i8 name="level">
			<f32 name="x,y,z">
		</version>
	</packet>`

	for b.Loop() {
		_, err := Parse(pml)
		if err != nil {
			b.Fatal(err)
		}
	}
}

func BenchmarkMediumPacket(b *testing.B) {
	pml := `<packet name="Medium">
		<version number="1">
			<i32 name="id,account_id,session_id">
			<str16 name="name,guild_name">
			<i8 name="level,race,class">
			<f32 name="x,y,z,heading">
			<color name="skin_color,hair_color">
		</version>
	</packet>`

	for b.Loop() {
		_, err := Parse(pml)
		if err != nil {
			b.Fatal(err)
		}
	}
}

func BenchmarkLargePacket(b *testing.B) {
	pml := `<packet name="Large">
		<version number="1">
			<i32 name="a1,a2,a3,a4,a5,a6,a7,a8,a9,a10">
			<str16 name="s1,s2,s3,s4,s5">
			<f32 name="f1,f2,f3,f4,f5,f6,f7,f8">
			<color name="c1,c2,c3,c4">
			<i8 name="b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12">
		</version>
	</packet>`

	for b.Loop() {
		_, err := Parse(pml)
		if err != nil {
			b.Fatal(err)
		}
	}
}

func BenchmarkArrayPacket(b *testing.B) {
	pml := `<packet name="ArrayPacket">
		<version number="1">
			<i8 name="count">
			<array name="items" count="var:count">
				<i32 name="id">
				<str16 name="name">
				<color name="color">
				<f32 name="x,y,z">
			</array>
		</version>
	</packet>`

	for b.Loop() {
		_, err := Parse(pml)
		if err != nil {
			b.Fatal(err)
		}
	}
}

func BenchmarkMultiVersionPacket(b *testing.B) {
	pml := `<packet name="MultiVersion">
		<version number="1">
			<i32 name="id">
			<str16 name="name">
		</version>
		<version number="100">
			<i32 name="id">
			<str16 name="name">
			<i8 name="level">
		</version>
		<version number="500">
			<i32 name="id">
			<str16 name="name">
			<i8 name="level">
			<color name="color">
		</version>
	</packet>`

	for b.Loop() {
		_, err := Parse(pml)
		if err != nil {
			b.Fatal(err)
		}
	}
}

// Helper function to compare slices
func equalSlices(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}
