using EventFlow.Aggregates;
using System.Text;

namespace MyTelegram.TestApp;

public class JsonSerializeContextGenerator2
{

    public static void GenerateAllJsonSerializeContextCode()
    {
        //var names = new List<string> { "AuthCache" };
        //var types = typeof(AppCodeCreatedIntegrationEvent).Assembly.GetTypes()
        //    .Where(t => t.Name.EndsWith("Event") ||
        //                t.Name.EndsWith("Input") ||
        //                t.Name.EndsWith("Response") ||
        //                t.Name.EndsWith("Message") ||
        //                names.Contains(t.Name))
        //    .OrderBy(p => p.Name)
        //    .ToList();

        var allTypes = GetTypes();

        var sb = new StringBuilder();

        sb.AppendLine("// <auto-generated/>\r\n// ReSharper disable All");
        sb.AppendLine("using System.Text.Json.Serialization;");
        sb.AppendLine();
        sb.AppendLine("namespace MyTelegram.Messenger.NativeAot;");
        sb.AppendLine();
        sb.AppendLine("#if !DEBUG");
        sb.AppendLine();

        foreach (var kv in allTypes)
        {
            sb.AppendLine($"// {kv.Key}");
            foreach (var type in kv.Value.OrderBy(p => p.Namespace).ThenBy(p => p.Name))
            {
                if (type.IsPublic)
                {
                    sb.AppendLine($"[JsonSerializable(typeof({type.Namespace}.{type.Name}))]");
                }
            }

            sb.AppendLine();
        }

        sb.AppendLine();
        sb.AppendLine("[JsonSerializable(typeof(UserReactionItem))]");
        sb.AppendLine("[JsonSerializable(typeof(List<UserReactionItem>))]");
        sb.AppendLine("[JsonSerializable(typeof(List<MyTelegram.TimeZoneItem>))]");
        sb.AppendLine("[JsonSerializable(typeof(Reaction))]");
        sb.AppendLine("[JsonSerializable(typeof(ReactionCount))]");
        //sb.AppendLine("[JsonSerializable(typeof(MyTelegram.Messenger.Handlers.Impl.CachedFutureSalt))]");
        sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.MongoDB.ValueObjects.MongoDbEventDataModel))]");
        sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.MongoDB.ValueObjects.MongoDbCounterDataModel))]");
        sb.AppendLine("#endif");
        sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.MongoDB.ValueObjects.MongoDbSnapshotDataModel))]");
        sb.AppendLine();
        sb.AppendLine("[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]");
        sb.AppendLine("public partial class MyMessengerJsonContext : JsonSerializerContext");
        sb.AppendLine("{");
        sb.AppendLine("}");

        var fileName = "MyMessengerJsonContext.g.cs";
        File.WriteAllText(fileName, sb.ToString());
        var destPath = $@"../../../../MyTelegram.Messenger/NativeAot/{fileName}";
        File.Copy(fileName, destPath, true);
        Console.WriteLine($"Generate {fileName} successfully.");
        var destPath2 = $@"../../../../MyTelegram.DataSeeder/{fileName}";
        File.Copy(fileName, destPath2, true);
    }

    private static Dictionary<string, IEnumerable<Type>> GetTypes()
    {
        var dict = new Dictionary<string, IEnumerable<Type>>();
        //var names = new List<string>
        //{ 
        //    "AuthCache",
        //    "CachedAuthKey",
        //    "DomainEventMessage",
        //    "UserCacheItem"
        //};
        //var types = typeof(AppCodeCreatedIntegrationEvent).Assembly.GetTypes()
        //    .Where(t => t.Name.EndsWith("Event") ||
        //                t.Name.EndsWith("Input") ||
        //                t.Name.EndsWith("Response") ||
        //                t.Name.EndsWith("Message") ||
        //                names.Contains(t.Name))
        //    .OrderBy(p => p.Name)
        //    .ToList();

        //dict.Add("MyTelegram.Core", types);


        //var names2 = new List<string>()
        //{
        //    "Peer",
        //    "PhotoSize",
        //    "VideoSize",
        //    "VideoSizeEmojiMarkup",
        //    "WallPaperSettings"
        //};
        //var types2 = typeof(PhotoSize).Assembly.GetTypes()
        //        .Where(t => names2.Contains(t.Name))
        //        .OrderBy(p => p.Name)
        //        .ToList()
        //    ; 

        //dict.Add("MyTelegram.Domain.Shared", types2);


        //var types3 = new List<Type>(new[]
        //{
        //    //typeof(Metadata),
        //    //typeof(SnapshotMetadata),
        //    //typeof(DispatchToAsynchronousEventSubscribersJob),
        //    typeof(MongoDbEventDataModel)
        //});

        //dict.Add("EventFlow", types3);

        var names4 = new List<string>
        {
            nameof(UserReactionItem),
            nameof(TimeZoneItem)
        };
        var types4 = new List<Type>();
        var baseType = typeof(IAggregateEvent);
        types4 = typeof(MyTelegram.Domain.Aggregates.User.UserAggregate).Assembly.GetTypes()
            .Where(p => p.Name.EndsWith("Event") || names4.Contains(p.Name) ||
                        p.Name.EndsWith("CacheItem") ||
                        p.Name.EndsWith("Snapshot") ||
                        (p.IsAssignableTo(baseType)&&!p.IsAbstract)

            )
            .ToList();

        dict.Add("MyTelegram.Domain", types4);


        return dict;
    }
}
