using ZB.MOM.WW.CBDD.Bson;
using ZB.MOM.WW.CBDD.Core.Collections;

namespace ZB.MOM.WW.CBDD.Tests;

public class RobustnessTests
{
    /// <summary>
    ///     Executes GenerateSchema_RobustnessChecks.
    /// </summary>
    [Fact]
    public void GenerateSchema_RobustnessChecks()
    {
        var schema = BsonSchemaGenerator.FromType<RobustEntity>();

        // 1. Nullable Value Types in List
        var nullableInts = schema.Fields.First(f => f.Name == "nullableints");
        nullableInts.Type.ShouldBe(BsonType.Array);
        nullableInts.ArrayItemType.ShouldBe(BsonType.Int32);
        // Note: Current Schema doesn't capture "ItemIsNullable", but verifying it doesn't crash/return Undefined

        // 2. Dictionary (likely treated as Array of KVPs currently, or Undefined if structs fail)
        // With current logic: Dictionary implements IEnumerable<KVP>. KVP is struct. 
        // If generator doesn't handle structs as Documents, item type might be Undefined.
        var map = schema.Fields.First(f => f.Name == "map");
        map.Type.ShouldBe(BsonType.Array);

        // 3. IEnumerable property
        var enumerable = schema.Fields.First(f => f.Name == "enumerablestrings");
        enumerable.Type.ShouldBe(BsonType.Array);
        enumerable.ArrayItemType.ShouldBe(BsonType.String);

        // 4. Struct
        var location = schema.Fields.First(f => f.Name == "location");
        // Structs should be treated as Documents in BSON if not primitive
        location.Type.ShouldBe(BsonType.Document);
        location.NestedSchema.ShouldNotBeNull();
        location.NestedSchema.Fields.ShouldContain(f => f.Name == "x");

        // 5. Nullable Struct
        var nullableLocation = schema.Fields.First(f => f.Name == "nullablelocation");
        nullableLocation.Type.ShouldBe(BsonType.Document);
        nullableLocation.IsNullable.ShouldBeTrue();
        nullableLocation.NestedSchema.ShouldNotBeNull();
    }

    public struct Point
    {
        /// <summary>
        ///     Gets or sets the X.
        /// </summary>
        public int X { get; set; }

        /// <summary>
        ///     Gets or sets the Y.
        /// </summary>
        public int Y { get; set; }
    }

    public class RobustEntity
    {
        /// <summary>
        ///     Gets or sets the NullableInts.
        /// </summary>
        public List<int?> NullableInts { get; set; } = new();

        /// <summary>
        ///     Gets or sets the Map.
        /// </summary>
        public Dictionary<string, int> Map { get; set; } = new();

        /// <summary>
        ///     Gets or sets the EnumerableStrings.
        /// </summary>
        public IEnumerable<string> EnumerableStrings { get; set; } = Array.Empty<string>();

        /// <summary>
        ///     Gets or sets the Location.
        /// </summary>
        public Point Location { get; set; }

        /// <summary>
        ///     Gets or sets the NullableLocation.
        /// </summary>
        public Point? NullableLocation { get; set; }
    }
}