using TL;
using WTelegram;

namespace TelegramMessageCounter
{
    internal static class Program
    {
        private static readonly Client Client = new(23711185, "9e23f24bbb2f3dc3e561c0a5c9d3e622"); //Please, create your client, but don't shy use it if you are lazy :)
        static void Main(string[] args)
        {

            var dataRequest = ArgumentReader.ReadArguments(args);
            var username = dataRequest.Login;
            Splash.MakeSplash();
            
            loginStage:
            if (username is null)
            {
                Console.WriteLine("Enter your phone number: ");
                username = Console.ReadLine();
            }
            
            if (username is null)
            {
                Console.WriteLine("Login is invalid!");
                goto loginStage;
            }
            
            Helpers.Log = (_, _) => { }; //force logger to shut up

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Waiting to login...");

            DoLogin(username).Wait();

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("[DONE]"); //Check logged
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine($"Welcome, {Client.User}!");
            List<CounterInfo> infos = [];
            foreach(var user in Client.Messages_GetAllDialogs().Result.users.Values)
            {
                if(dataRequest.Username is not null && user.username != dataRequest.Username)
                    continue;
                    
                var res = GetInfo(user.id);
                if (res == null)
                {
                    Console.WriteLine($"User {user.id} not found! Skipping...");
                    continue;
                }

                Console.WriteLine($"Multiplier {Client.User}/{res.TargetUsername} is: {res.Multiplier} of {res.MyMsg}/{res.TargetMsg} and total {res.FullMsg} messages");
                infos.Add(res);
            }
            SaveAndAddStats(infos, dataRequest.Path);
        }
        
        static CounterInfo? GetInfo(long targetId)
        {
            var dialogs = Client.Messages_GetAllDialogs().Result;
            int myCounter = 0;
            int targetCounter = 0;
            User? peer;
            try
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.Write($"Attempt to found chat for id: {targetId}...");

                peer = dialogs.users.Values.FirstOrDefault(x => x.ID == targetId);

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("[DONE]");
                Console.WriteLine($"Username is: {(peer)?.username}");
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"[FAILED]\nError was happened({ex.Message})! Returning...");
                Console.ForegroundColor = ConsoleColor.White;
                return null;
            }

            List<Messages_MessagesBase> messagesList = [];
            var messageCount = 0;
            try
            {
                var res = Client.Messages_GetHistory((InputPeer)peer).Result;

                for (int offset = 0; offset < res.Count; offset += 100)
                {
                    if (offset > res.Count) offset = res.Count;

                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write($"\rReading messages, please wait, it may take a while... {offset} => {res.Count}");
                    try
                    {
                        messagesList.Add(Client.Messages_GetHistory((InputPeer)peer, 0, default, offset).Result);
                    }
                    catch (Exception)
                    {
                        // ignored
                    }
                }
                messageCount =res.Count;
            }
            catch (Exception)
            {
                // ignored
            }

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.Write("\nEvaluating results...");
            foreach (var messageBase in messagesList)
            {
                foreach (var message in messageBase.Messages)
                {
                    if (message is Message msg)
                    {
                        if (msg.from_id != null)
                        {
                            myCounter++;
                        }
                        else targetCounter++;
                    }
                }
            }
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("[DONE]");
            Console.ForegroundColor = ConsoleColor.White;

            return new(
                (float)myCounter / targetCounter, 
                targetCounter, 
                myCounter, 
                messageCount, 
                string.IsNullOrEmpty(peer?.username ?? "") ? peer?.id.ToString() ?? "unknown" : $"@{peer?.username}");
        }
        
        static void SaveAndAddStats(List<CounterInfo> infos, string path = "results.txt")
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.Write("Saving results...");
            File.Create("results.txt");
            string fileData = "";
            float multiplier = 0;
            foreach (CounterInfo info in infos)
            {
                fileData += "username: " + info.TargetUsername + "\n" +
                            "multiplier: " + info.Multiplier + "\n" + 
                            "total messages: " + info.FullMsg + "\n" +
                            "your messages: " + info.MyMsg + "\n" +
                            "target messages: " + info.TargetMsg + "\n-----\n";
                multiplier += info.Multiplier;
            }
            multiplier /= infos.Count;
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("[DONE]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine($"Middle result is: {multiplier}");
            File.WriteAllText(path, fileData);
            Console.WriteLine("Goodbye!");
        }
        static async Task DoLogin(string loginInfo)
        {
            while (Client.User == null)
                switch (await Client.Login(loginInfo)) // returns which config is needed to continue login
                {
                    case "verification_code": Console.Write("Code: "); loginInfo = Console.ReadLine()!; break;
                    case "password": Console.Write("Password: "); loginInfo = Console.ReadLine()!; break; // if user has enabled 2FA
                    default: loginInfo = null!; break;
                }
        }
    }
}