using AyCode.Core.Extensions;
using AyCode.Core.Serializers.Attributes;
using AyCode.Core.Serializers.Binaries;
using MemoryPack;
using MessagePack;

namespace AyCode.Core.Tests.TestModels;

// ============================================================================
// _All_True family — every leaf marked [AcBinarySerializable(true)] (opt-out).
// All sub-references are _All_True-typed via the generic closing.
// `sealed` to enable AcBinary's non-polymorphic fast-path (no type-discriminator).
// ============================================================================

[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class SharedTag_All_True : SharedTagBase
{
}

[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class SharedCategory_All_True : SharedCategoryBase
{
}

[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class SharedUser_All_True : SharedUserBase<UserPreferences_All_True>
{
}

[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class UserPreferences_All_True : UserPreferencesBase
{
}

[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class MetadataInfo_All_True : MetadataInfoBase<MetadataInfo_All_True>
{
}

/// <summary>
/// Level 1: Main order - root of the hierarchy
/// </summary>
[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class TestOrder_All_True
    : TestOrderBase<TestOrderItem_All_True, SharedTag_All_True, SharedUser_All_True,
                    SharedCategory_All_True, MetadataInfo_All_True, UserPreferences_All_True>
{
}

/// <summary>
/// Level 2: Order item with pallets
/// </summary>
[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class TestOrderItem_All_True
    : TestOrderItemBase<TestPallet_All_True, SharedTag_All_True, SharedUser_All_True,
                        MetadataInfo_All_True, TestOrder_All_True, UserPreferences_All_True>
{
}

/// <summary>
/// Level 3: Pallet containing measurements
/// </summary>
[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class TestPallet_All_True
    : TestPalletBase<TestMeasurement_All_True, SharedTag_All_True, SharedUser_All_True,
                     SharedCategory_All_True, MetadataInfo_All_True, TestOrderItem_All_True,
                     UserPreferences_All_True>
{
}

/// <summary>
/// Level 4: Measurement with multiple points
/// </summary>
[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class TestMeasurement_All_True
    : TestMeasurementBase<TestMeasurementPoint_All_True, SharedTag_All_True, SharedUser_All_True,
                          TestPallet_All_True, UserPreferences_All_True>
{
}

/// <summary>
/// Level 5: Deepest level - measurement point
/// </summary>
[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class TestMeasurementPoint_All_True
    : TestMeasurementPointBase<SharedTag_All_True, SharedUser_All_True, TestMeasurement_All_True,
                               UserPreferences_All_True>
{
}

// ============================================================================
// _All_False family — every leaf marked [AcBinarySerializable(false)] (opt-in).
// All sub-references are _All_False-typed via the generic closing.
// `sealed` to enable AcBinary's non-polymorphic fast-path.
// ============================================================================

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class SharedTag_All_False : SharedTagBase
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class SharedCategory_All_False : SharedCategoryBase
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class SharedUser_All_False : SharedUserBase<UserPreferences_All_False>
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class UserPreferences_All_False : UserPreferencesBase
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class MetadataInfo_All_False : MetadataInfoBase<MetadataInfo_All_False>
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class TestOrder_All_False
    : TestOrderBase<TestOrderItem_All_False, SharedTag_All_False, SharedUser_All_False,
                    SharedCategory_All_False, MetadataInfo_All_False, UserPreferences_All_False>
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class TestOrderItem_All_False
    : TestOrderItemBase<TestPallet_All_False, SharedTag_All_False, SharedUser_All_False,
                        MetadataInfo_All_False, TestOrder_All_False, UserPreferences_All_False>
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class TestPallet_All_False
    : TestPalletBase<TestMeasurement_All_False, SharedTag_All_False, SharedUser_All_False,
                     SharedCategory_All_False, MetadataInfo_All_False, TestOrderItem_All_False,
                     UserPreferences_All_False>
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class TestMeasurement_All_False
    : TestMeasurementBase<TestMeasurementPoint_All_False, SharedTag_All_False, SharedUser_All_False,
                          TestPallet_All_False, UserPreferences_All_False>
{
}

[MemoryPackable]
[AcBinarySerializable(false)]
[MessagePackObject]
public sealed partial class TestMeasurementPoint_All_False
    : TestMeasurementPointBase<SharedTag_All_False, SharedUser_All_False, TestMeasurement_All_False,
                               UserPreferences_All_False>
{
}

// ============================================================================
// MIXED family — drift reproduction (SGen-emit asymmetry check).
// Mirrors the FruitBank ProductDto / OrderDto / GenericAttributeDto attribute:
//   [AcBinarySerializable(false, true, false, true, false, false)]
//    meta=false, IdTracking=true, RefHandling=FALSE, Intern=true, Filter=false, Poly=false
//
// Parent: EnableRefHandlingFeature=FALSE  ◀ the asymmetry trigger
// Child:  EnableRefHandlingFeature=true (IId<int>, all features ON)
//
// Hypothesis (confirmed): the SGen reader-emit guard for collection-element / Complex /
// dictionary-value dispatch (EmitReadCollectionElement / EmitReadComplex / EmitReadDictionary)
// used to check the PARENT-level enableRefHandling flag. The writer-emit only depends on
// CHILD-level flags (ElementNeedsRefScan / DictValueNeedsRefScan / runtime
// UseTypeReferenceHandling). With runtime ReferenceHandling=All + duplicate child instances,
// the writer runtime emits ObjectRefFirst / ObjectRef, but the reader's zero-branch path
// couldn't decode them → DECIMAL_DRIFT on MarkerDecimal after the Children list or
// ChildrenMap dictionary.
//
// Fix: parent-flag removed from reader guards; routing through RefAwareEmitPredicate
// (single source of truth shared with writer-side EmitDirectCollectionWrite).
//
// The existing _All_True family tests don't exercise this path because
// EnableRefHandlingFeature=true on the parent → reader emitted the full
// ref-aware switch → never hit the zero-branch bug.
// ============================================================================

[MemoryPackable]
[AcBinarySerializable(false, true, false, true, false, false)]
[MessagePackObject]
public sealed partial class TestRefAsymParent : AyCode.Core.Interfaces.IId<int>
{
    [Key(0)]
    public int Id { get; set; }

    [Key(1)]
    public System.Collections.Generic.List<TestRefAsymChild>? Children { get; set; }

    [Key(2)]
    public decimal MarkerDecimal { get; set; }

    [Key(3)]
    public System.Collections.Generic.Dictionary<int, TestRefAsymChild>? ChildrenMap { get; set; }

    [Key(4)]
    public decimal MarkerDecimal2 { get; set; }
}

[MemoryPackable]
[AcBinarySerializable(true)]
[MessagePackObject]
public sealed partial class TestRefAsymChild : AyCode.Core.Interfaces.IId<int>
{
    [Key(0)]
    public int Id { get; set; }

    [Key(1)]
    public string Name { get; set; } = "";
}
