using ZB.MOM.WW.CBDD.Bson;
using ZB.MOM.WW.CBDD.Core.Collections;
using Xunit;
using System.Collections.Generic;
using System;
using System.Linq;

namespace ZB.MOM.WW.CBDD.Tests;

public class BsonSchemaTests
{
    public class SimpleEntity
    {
        /// <summary>
        /// Gets or sets the identifier.
        /// </summary>
        public ObjectId Id { get; set; }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        public string Name { get; set; } = string.Empty;

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

        /// <summary>
        /// Gets or sets a value indicating whether the entity is active.
        /// </summary>
        public bool IsActive { get; set; }
    }

    /// <summary>
    /// Verifies schema generation for a simple entity.
    /// </summary>
    [Fact]
    public void GenerateSchema_SimpleEntity()
    {
        var schema = BsonSchemaGenerator.FromType<SimpleEntity>();

        schema.Title.ShouldBe("SimpleEntity");
        schema.Fields.Count.ShouldBe(4);

        var idField = schema.Fields.First(f => f.Name == "_id");
        idField.Type.ShouldBe(BsonType.ObjectId);

        var nameField = schema.Fields.First(f => f.Name == "name");
        nameField.Type.ShouldBe(BsonType.String);

        var ageField = schema.Fields.First(f => f.Name == "age");
        ageField.Type.ShouldBe(BsonType.Int32);
    }

    public class CollectionEntity
    {
        /// <summary>
        /// Gets or sets tags.
        /// </summary>
        public List<string> Tags { get; set; } = new();

        /// <summary>
        /// Gets or sets scores.
        /// </summary>
        public int[] Scores { get; set; } = Array.Empty<int>();
    }

    /// <summary>
    /// Verifies schema generation for collection fields.
    /// </summary>
    [Fact]
    public void GenerateSchema_Collections()
    {
        var schema = BsonSchemaGenerator.FromType<CollectionEntity>();

        var tags = schema.Fields.First(f => f.Name == "tags");
        tags.Type.ShouldBe(BsonType.Array);
        tags.ArrayItemType.ShouldBe(BsonType.String);

        var scores = schema.Fields.First(f => f.Name == "scores");
        scores.Type.ShouldBe(BsonType.Array);
        scores.ArrayItemType.ShouldBe(BsonType.Int32);
    }

    public class NestedEntity
    {
        /// <summary>
        /// Gets or sets the parent entity.
        /// </summary>
        public SimpleEntity Parent { get; set; } = new();
    }

    /// <summary>
    /// Verifies schema generation for nested document fields.
    /// </summary>
    [Fact]
    public void GenerateSchema_Nested()
    {
        var schema = BsonSchemaGenerator.FromType<NestedEntity>();

        var parent = schema.Fields.First(f => f.Name == "parent");
        parent.Type.ShouldBe(BsonType.Document);
        parent.NestedSchema.ShouldNotBeNull();
        parent.NestedSchema.Fields.ShouldContain(f => f.Name == "_id");
    }

    public class ComplexCollectionEntity
    {
        /// <summary>
        /// Gets or sets items.
        /// </summary>
        public List<SimpleEntity> Items { get; set; } = new();
    }

    /// <summary>
    /// Verifies schema generation for collections of complex types.
    /// </summary>
    [Fact]
    public void GenerateSchema_ComplexCollection()
    {
        var schema = BsonSchemaGenerator.FromType<ComplexCollectionEntity>();

        var items = schema.Fields.First(f => f.Name == "items");
        items.Type.ShouldBe(BsonType.Array);
        // items.ArrayItemType.ShouldBe(BsonType.Document); // Wait, my generator logic might return Array here? No, item type logic...

        // Let's verify generator logic for complex array item type
        // In generator: (BsonType.Array, itemNested, itemBsonType)
        // itemBsonType for SimpleEntity should be Document

        items.ArrayItemType.ShouldBe(BsonType.Document);
        items.NestedSchema.ShouldNotBeNull();
        items.NestedSchema.Fields.ShouldContain(f => f.Name == "_id");
    }
}
