using EventFlow.Aggregates;
using EventFlow.Provided.Jobs;
using EventFlow.Snapshots;
using MyTelegram.Core;
using MyTelegram.Services.Services;
using System.Text;

namespace MyTelegram.TestApp;

public class JsonSerializeContextGenerator
{

    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.Services.NativeAot;");
        sb.AppendLine();
        sb.AppendLine("#if !DEBUG");
        sb.AppendLine();

        sb.AppendLine($"// Count:{allTypes.Sum(x => x.Value.Count())}");

        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();
        }

        /*[JsonSerializable(typeof(global::EventFlow.Aggregates.Metadata))]
           [JsonSerializable(typeof(global::EventFlow.Provided.Jobs.DispatchToAsynchronousEventSubscribersJob))]
           [JsonSerializable(typeof(global::EventFlow.Snapshots.SnapshotMetadata))]*/
        sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.Aggregates.Metadata))]");
        sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.Provided.Jobs.DispatchToAsynchronousEventSubscribersJob))]");
        sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.Snapshots.SnapshotMetadata))]");
        sb.AppendLine($"[JsonSerializable(typeof(System.Collections.Generic.List<PhotoSize>))]");
        sb.AppendLine($"[JsonSerializable(typeof(System.Collections.Generic.List<VideoSize>))]");
        sb.AppendLine($"[JsonSerializable(typeof(System.Collections.Generic.List<FutureAuthTokenCacheItem>))]");
        sb.AppendLine("#endif");
        sb.AppendLine($"[JsonSerializable(typeof(System.Collections.Generic.List<FutureSaltCacheItem>))]");
        //sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.MongoDB.ValueObjects.MongoDbEventDataModel))]");
        //sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.MongoDB.ValueObjects.MongoDbCounterDataModel))]");
        //sb.AppendLine("[JsonSerializable(typeof(global::EventFlow.MongoDB.ValueObjects.MongoDbSnapshotDataModel))]");

        sb.AppendLine();

        sb.AppendLine("[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]");
        sb.AppendLine("public partial class MyJsonSerializeContext : JsonSerializerContext");
        sb.AppendLine("{");
        sb.AppendLine("}");


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

    private static Dictionary<string, IEnumerable<Type>> GetTypes()
    {
        var dict = new Dictionary<string, IEnumerable<Type>>();
        var names = new List<string>
        { 
            //"AuthCacheItem",
            //"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") ||
                        t.Name.EndsWith("CacheItem")||
                        names.Contains(t.Name))
            .OrderBy(p => p.Name)
            .ToList();

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


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

        //types2.Add(typeof(List<PhotoSize>));
        //types2.Add(typeof(List<VideoSize>));

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


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

        dict.Add("EventFlow", types3);

        //var types4 = new List<Type>();
        //types4 = typeof(MyTelegram.Domain.Aggregates.User.UserAggregate).Assembly.GetTypes()
        //    .Where(p => p.Name.EndsWith("Event"))
        //    .ToList();

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


        return dict;
    }
}
