using AyCode.Core.Extensions; using AyCode.Core.Interfaces; using AyCode.Core.Serializers.Attributes; using AyCode.Core.Serializers.Binaries; using AyCode.Core.Serializers.Jsons; using MemoryPack; using MessagePack; using MongoDB.Bson.Serialization.Attributes; using Newtonsoft.Json; namespace AyCode.Core.Tests.TestModels; #region Shared Enums /// /// Common status enum for all test entities /// public enum TestStatus { Pending = 5, Active = 10, Processing = 20, Completed = 30, Shipped = 40, OnHold = 50 } /// /// Priority levels for tasks and projects /// public enum TestPriority { Low = 0, Medium = 1, High = 2, Critical = 3 } /// /// User roles for testing /// public enum TestUserRole { User = 0, Manager = 1, Admin = 2 } #endregion #region Shared Reference Types (IId-based for $id/$ref testing) /// /// Shared tag/label - used across multiple entities for cross-reference testing. /// Implements IId<int> for semantic $id/$ref serialization. /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class SharedTag : IId { [Key(0)] public int Id { get; set; } [Key(1)] public string Name { get; set; } = ""; [AcStringIntern(true)] [Key(2)] public string Color { get; set; } = "#000000"; [Key(3)] public int Priority { get; set; } [Key(4)] public bool IsActive { get; set; } = true; [Key(5)] public DateTime CreatedAt { get; set; } = DateTime.UtcNow; [Key(6)] public string? Description { get; set; } } /// /// Shared category - for hierarchical cross-reference testing. /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class SharedCategory : IId { [Key(0)] public int Id { get; set; } [Key(1)] public string Name { get; set; } = ""; [Key(2)] public string? Description { get; set; } [Key(3)] public int SortOrder { get; set; } [Key(4)] public bool IsDefault { get; set; } [Key(5)] public int? ParentCategoryId { get; set; } [Key(6)] public DateTime CreatedAt { get; set; } = DateTime.UtcNow; [Key(7)] public DateTime? UpdatedAt { get; set; } } /// /// Shared user reference - appears in many places to test $ref deduplication. /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class SharedUser : IId { [Key(0)] public int Id { get; set; } [Key(1)] public string Username { get; set; } = ""; [Key(2)] public string Email { get; set; } = ""; [Key(3)] public string FirstName { get; set; } = ""; [Key(4)] public string LastName { get; set; } = ""; [Key(5)] public bool IsActive { get; set; } = true; [Key(6)] public TestUserRole Role { get; set; } = TestUserRole.User; [Key(7)] public DateTime? LastLoginAt { get; set; } [Key(8)] public DateTime CreatedAt { get; set; } = DateTime.UtcNow; [Key(9)] public UserPreferences? Preferences { get; set; } } /// /// User preferences - non-IId nested object /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class UserPreferences { [AcStringIntern(true)] [Key(0)] public string Theme { get; set; } = "light"; [AcStringIntern(true)] [Key(1)] public string Language { get; set; } = "en-US"; [Key(2)] public bool NotificationsEnabled { get; set; } = true; [AcStringIntern(true)] [Key(3)] public string? EmailDigestFrequency { get; set; } } #endregion #region Non-IId Metadata (Newtonsoft numeric $id/$ref testing) /// /// Non-IId metadata class - uses Newtonsoft PreserveReferencesHandling (numeric $id/$ref). /// Does NOT implement IId, so uses standard Newtonsoft reference tracking. /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class MetadataInfo { [AcStringIntern(true)] [Key(0)] public string Key { get; set; } = ""; [AcStringIntern(true)] [Key(1)] public string Value { get; set; } = ""; [Key(2)] public DateTime Timestamp { get; set; } = DateTime.UtcNow; /// /// Nested metadata for deep Newtonsoft reference testing /// [Key(3)] public MetadataInfo? ChildMetadata { get; set; } } #endregion #region 5-Level Test Hierarchy (Order -> Item -> Pallet -> Measurement -> Point) /// /// Level 1: Main order - root of the hierarchy /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class TestOrder : IId { [Key(0)] public int Id { get; set; } [Key(1)] public string OrderNumber { get; set; } = ""; [Key(2)] public TestStatus Status { get; set; } = TestStatus.Pending; [Key(3)] public DateTime CreatedAt { get; set; } = DateTime.UtcNow; [Key(4)] public DateTime? PaidDateUtc { get; set; } [Key(5)] public decimal TotalAmount { get; set; } // Level 2 collection [Key(6)] public List Items { get; set; } = []; // Shared reference properties (for $id/$ref testing) [Key(7)] public SharedTag? PrimaryTag { get; set; } [Key(8)] public SharedTag? SecondaryTag { get; set; } [Key(9)] public SharedUser? Owner { get; set; } [Key(10)] public SharedCategory? Category { get; set; } // Collection of shared references [Key(11)] public List Tags { get; set; } = []; // Non-IId metadata (for Newtonsoft $ref testing) [Key(12)] public MetadataInfo? OrderMetadata { get; set; } [Key(13)] public MetadataInfo? AuditMetadata { get; set; } [Key(14)] public List MetadataList { get; set; } = []; // NoMerge collection for testing replace behavior [JsonNoMergeCollection] [Key(15)] public List NoMergeItems { get; set; } = []; // Parent reference - ignored by all serializers to prevent circular references [MemoryPackIgnore] [JsonIgnore] [IgnoreMember] [BsonIgnore] public object? Parent { get; set; } } /// /// Level 1: Main order - root of the hierarchy /// [AcBinarySerializable(true)] public partial class TestOrder_Circ_Ref : IId { public int Id { get; set; } public string OrderNumber { get; set; } = ""; public TestStatus Status { get; set; } = TestStatus.Pending; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? PaidDateUtc { get; set; } public decimal TotalAmount { get; set; } // Level 2 collection public List Items { get; set; } = []; // Shared reference properties (for $id/$ref testing) public SharedTag? PrimaryTag { get; set; } public SharedTag? SecondaryTag { get; set; } public SharedUser? Owner { get; set; } public SharedCategory? Category { get; set; } // Collection of shared references public List Tags { get; set; } = []; public MetadataInfo? OrderMetadata { get; set; } public MetadataInfo? AuditMetadata { get; set; } public List MetadataList { get; set; } = []; // NoMerge collection for testing replace behavior [JsonNoMergeCollection] public List NoMergeItems { get; set; } = []; public object? Parent { get; set; } } /// /// Level 2: Order item with pallets /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class TestOrderItem : IId { [Key(0)] public int Id { get; set; } [AcStringIntern(true)] [Key(1)] public string ProductName { get; set; } = ""; [Key(2)] public int Quantity { get; set; } [Key(3)] public decimal UnitPrice { get; set; } [Key(4)] public TestStatus Status { get; set; } = TestStatus.Pending; // Level 3 collection [Key(5)] public List Pallets { get; set; } = []; // Shared references [Key(6)] public SharedTag? Tag { get; set; } [Key(7)] public SharedUser? Assignee { get; set; } [Key(8)] public MetadataInfo? ItemMetadata { get; set; } // Parent reference - ignored by all serializers to prevent circular references [MemoryPackIgnore] [JsonIgnore] [IgnoreMember] [BsonIgnore] public TestOrder? ParentOrder { get; set; } } /// /// Level 2: Order item with pallets /// [AcBinarySerializable(true)] public partial class TestOrderItem_Circ_Ref : IId { public int Id { get; set; } [AcStringIntern(true)] public string ProductName { get; set; } = ""; public int Quantity { get; set; } public decimal UnitPrice { get; set; } public TestStatus Status { get; set; } = TestStatus.Pending; // Level 3 collection public List Pallets { get; set; } = []; // Shared references public SharedTag? Tag { get; set; } public SharedUser? Assignee { get; set; } public MetadataInfo? ItemMetadata { get; set; } public TestOrder_Circ_Ref? ParentOrder { get; set; } } /// /// Level 3: Pallet containing measurements /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class TestPallet : IId { [Key(0)] public int Id { get; set; } [Key(1)] public string PalletCode { get; set; } = ""; [Key(2)] public int TrayCount { get; set; } [Key(3)] public TestStatus Status { get; set; } = TestStatus.Pending; [Key(4)] public double Weight { get; set; } // Level 4 collection [Key(5)] public List Measurements { get; set; } = []; // Shared IId references for better reference testing [Key(6)] public SharedTag? Tag { get; set; } [Key(7)] public SharedUser? Inspector { get; set; } [Key(8)] public SharedCategory? Category { get; set; } // Non-IId shared references [Key(9)] public MetadataInfo? PalletMetadata { get; set; } // Parent reference - ignored by all serializers to prevent circular references [MemoryPackIgnore] [JsonIgnore] [IgnoreMember] [BsonIgnore] public TestOrderItem? ParentItem { get; set; } } /// /// Level 4: Measurement with multiple points /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class TestMeasurement : IId { [Key(0)] public int Id { get; set; } [Key(1)] public string Name { get; set; } = ""; [Key(2)] public double TotalWeight { get; set; } [Key(3)] public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Level 5 collection [Key(4)] public List Points { get; set; } = []; // Shared IId references for better reference testing [Key(5)] public SharedTag? Tag { get; set; } [Key(6)] public SharedUser? Operator { get; set; } // Parent reference - ignored by all serializers to prevent circular references [MemoryPackIgnore] [JsonIgnore] [IgnoreMember] [BsonIgnore] public TestPallet? ParentPallet { get; set; } } /// /// Level 5: Deepest level - measurement point /// [MemoryPackable] [AcBinarySerializable(true)] [MessagePackObject] public partial class TestMeasurementPoint : IId { [Key(0)] public int Id { get; set; } [Key(1)] public string Label { get; set; } = ""; [Key(2)] public double Value { get; set; } [Key(3)] public DateTime MeasuredAt { get; set; } = DateTime.UtcNow; // Shared IId reference for better reference testing (many points share same tag/user) [Key(4)] public SharedTag? Tag { get; set; } [Key(5)] public SharedUser? Verifier { get; set; } // Parent reference - ignored by all serializers to prevent circular references [MemoryPackIgnore] [JsonIgnore] [IgnoreMember] [BsonIgnore] public TestMeasurement? ParentMeasurement { get; set; } } #endregion #region Guid-based IId types /// /// Order with Guid Id - for testing Guid-based IId /// [AcBinarySerializable(true)] public class TestGuidOrder : IId { public Guid Id { get; set; } public string Code { get; set; } = ""; public List Items { get; set; } = []; public int Count { get; set; } } /// /// Item with Guid Id /// [AcBinarySerializable(true)] public class TestGuidItem : IId { public Guid Id { get; set; } public string Name { get; set; } = ""; public int Qty { get; set; } } #endregion #region Test-specific classes /// /// Simulates NopCommerce GenericAttribute - stores key-value pairs where DateTime values /// are stored as strings in the database. /// [AcBinarySerializable(true)] public class TestGenericAttribute { public int Id { get; set; } public string Key { get; set; } = ""; public string Value { get; set; } = ""; } /// /// DTO with GenericAttributes collection - simulates OrderDto with string-stored DateTime values. /// This reproduces the production bug where Binary serialization was thought to corrupt DateTime strings. /// [AcBinarySerializable(true)] public class TestDtoWithGenericAttributes : IId { public int Id { get; set; } public string Name { get; set; } = ""; public List GenericAttributes { get; set; } = []; } /// /// Order with nullable collections for null vs empty testing /// [AcBinarySerializable(true)] public class TestOrderWithNullableCollections { public int Id { get; set; } public string OrderNumber { get; set; } = ""; public List? Items { get; set; } public List? Tags { get; set; } } /// /// Class with all primitive types for WASM/serialization testing /// [MemoryPackable] [AcBinarySerializable(true)] public partial class PrimitiveTestClass { public int IntValue { get; set; } public long LongValue { get; set; } public double DoubleValue { get; set; } public decimal DecimalValue { get; set; } public float FloatValue { get; set; } public bool BoolValue { get; set; } public string StringValue { get; set; } = ""; public Guid GuidValue { get; set; } public DateTime DateTimeValue { get; set; } public TestStatus EnumValue { get; set; } public byte ByteValue { get; set; } public short ShortValue { get; set; } public int? NullableInt { get; set; } public int? NullableIntNull { get; set; } } /// /// Class with extended primitive types for full serializer coverage. /// Includes DateTimeOffset, TimeSpan, Dictionary, null properties. /// [AcBinarySerializable(true)] public class ExtendedPrimitiveTestClass { public int Id { get; set; } public string Name { get; set; } = ""; // Extended primitive types not covered in PrimitiveTestClass public DateTimeOffset DateTimeOffsetValue { get; set; } public TimeSpan TimeSpanValue { get; set; } public uint UIntValue { get; set; } public ulong ULongValue { get; set; } public ushort UShortValue { get; set; } public sbyte SByteValue { get; set; } public char CharValue { get; set; } // Dictionary property for WriteDictionary coverage in object context public Dictionary? Counts { get; set; } public Dictionary? Labels { get; set; } // Nullable properties that will be null public string? NullString { get; set; } public TestOrderItem? NullObject { get; set; } // Nested object for complex serialization public SharedTag? Tag { get; set; } } /// /// Class with array of objects containing null items for WriteNull coverage /// [AcBinarySerializable(true)] public class ObjectWithNullItems { public int Id { get; set; } public List MixedItems { get; set; } = []; } #endregion #region Property Mismatch DTOs (Server has more properties than Client) /// /// "Server-side" DTO with extra properties that the "client" doesn't know about. /// Used to test SkipValue functionality when deserializing unknown properties. /// [AcBinarySerializable(true)] public class ServerCustomerDto : IId { public int Id { get; set; } // Common properties (both server and client have these) public string FirstName { get; set; } = ""; public string LastName { get; set; } = ""; // Extra properties (only server has these - client will skip them) public string Email { get; set; } = ""; public string Phone { get; set; } = ""; public string Address { get; set; } = ""; public string City { get; set; } = ""; public string Country { get; set; } = ""; public string PostalCode { get; set; } = ""; public string Company { get; set; } = ""; public string Department { get; set; } = ""; public string Notes { get; set; } = ""; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? LastLoginAt { get; set; } public TestStatus Status { get; set; } = TestStatus.Active; public bool IsVerified { get; set; } public int LoginCount { get; set; } public decimal Balance { get; set; } } /// /// "Client-side" DTO with fewer properties than the server version. /// When deserializing ServerCustomerDto data into this type, /// the deserializer must skip unknown properties correctly /// while still maintaining string intern table consistency. /// [AcBinarySerializable(true)] public class ClientCustomerDto : IId { public int Id { get; set; } // Only basic properties - client doesn't need all server fields public string FirstName { get; set; } = ""; public string LastName { get; set; } = ""; } /// /// Server DTO with nested objects that client doesn't know about. /// Tests skipping complex nested structures. /// [AcBinarySerializable(true)] public class ServerOrderWithExtras : IId { public int Id { get; set; } public string OrderNumber { get; set; } = ""; public decimal TotalAmount { get; set; } // Nested object that client doesn't have public ServerCustomerDto? Customer { get; set; } // List of objects that client doesn't know about public List RelatedCustomers { get; set; } = []; // Extra simple properties public string InternalNotes { get; set; } = ""; public string ProcessingCode { get; set; } = ""; } /// /// Client version of the order - doesn't have Customer/RelatedCustomers properties. /// [AcBinarySerializable(true)] public class ClientOrderSimple : IId { public int Id { get; set; } public string OrderNumber { get; set; } = ""; public decimal TotalAmount { get; set; } } #endregion