using System;
using System.Reflection;

namespace NetworkResurrector.Api.Application.Helpers
{
    internal static class Randomizer
    {
        private static readonly Random random = new Random();

        public static string Randomize(string originalString)
        {
            var newString = new char[originalString.Length];

            for (int i = 0; i < originalString.Length; i++)
            {
                if (char.IsLetter(originalString[i]))
                {
                    if (char.IsUpper(originalString[i]))
                    {
                        newString[i] = GetRandomUpperLetter();
                    }
                    else
                    {
                        newString[i] = GetRandomLowerLetter();
                    }
                }
                else if (char.IsDigit(originalString[i]))
                {
                    newString[i] = GetRandomDigit();
                }
                else
                {
                    newString[i] = originalString[i];
                }
            }

            var newStringValue = new string(newString);
            return newStringValue;
        }

        public static void ReplaceStringProperties(object obj)
        {
            if (obj == null) return;

            var objectType = obj.GetType();
            var properties = objectType.GetProperties();

            if (obj is string)
            {
                var originalString = (string)obj;
                var newStringValue = Randomize(originalString);

                if (newStringValue != originalString)
                {
                    objectType.InvokeMember("value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, Type.DefaultBinder, obj, new object[] { newStringValue });
                }
            }
            else if (obj is Array array)
            {
                foreach (var item in array)
                {
                    ReplaceStringProperties(item);
                }
            }
            else
            {
                foreach (var property in properties)
                {
                    if (property.PropertyType == typeof(string))
                    {
                        var originalString = (string)property.GetValue(obj);
                        var newString = new char[originalString.Length];

                        for (int i = 0; i < originalString.Length; i++)
                        {
                            if (char.IsLetter(originalString[i]))
                            {
                                if (char.IsUpper(originalString[i]))
                                {
                                    newString[i] = GetRandomUpperLetter();
                                }
                                else
                                {
                                    newString[i] = GetRandomLowerLetter();
                                }
                            }
                            else if (char.IsDigit(originalString[i]))
                            {
                                newString[i] = GetRandomDigit();
                            }
                            else
                            {
                                newString[i] = originalString[i];
                            }
                        }

                        var newStringValue = new string(newString);

                        if (newStringValue != originalString)
                        {
                            property.SetValue(obj, newStringValue);
                        }
                    }
                    else
                    {
                        ReplaceStringProperties(property.GetValue(obj));
                    }
                }
            }
        }

        private static char GetRandomUpperLetter()
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            return chars[random.Next(chars.Length)];
        }

        private static char GetRandomLowerLetter()
        {
            const string chars = "abcdefghijklmnopqrstuvwxyz";
            return chars[random.Next(chars.Length)];
        }

        private static char GetRandomDigit()
        {
            const string chars = "0123456789";
            return chars[random.Next(chars.Length)];
        }
    }
}
