using System.Net.Http.Headers;
using Newtonsoft.Json;
using System.Linq.Expressions;
using Serialize.Linq.Serializers;
using System.Text;
using System.Globalization;
using tsDocumentos;
using RegistroPersonalAN.Components.Pages.InfoPersonasComponents;
using Microsoft.JSInterop;
using ClosedXML.Excel;
using MigraDocCore.DocumentObjectModel;
using Microsoft.Extensions.Configuration;


namespace RegistroPersonalAN.Models
{
    public class Utilidades
    {
        private static IConfiguration? Conf { get; set; }

        private static IConfiguration GetConfiguration()
        {
            if (Conf != null)
            {
                return Conf;
            }

            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
                ?? Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")
                ?? "Production";

            Conf = new ConfigurationBuilder()
                .SetBasePath(AppContext.BaseDirectory)
                .AddJsonFile("appsettings.json", optional: false)
                .AddJsonFile($"appsettings.{environment}.json", optional: true)
                .AddEnvironmentVariables()
                .Build();

            return Conf;
        }

        public static string RemoveDiacritics(string text)
        {
            var normalizedString = text.Normalize(NormalizationForm.FormD);
            var stringBuilder = new StringBuilder(capacity: normalizedString.Length);

            for (int i = 0; i < normalizedString.Length; i++)
            {
                char c = normalizedString[i];
                var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
                if (unicodeCategory != UnicodeCategory.NonSpacingMark)
                {
                    stringBuilder.Append(c);
                }
            }

            return stringBuilder
                .ToString()
                .Normalize(NormalizationForm.FormC);
        }

        public static string urlSwagger()
        {
            return GetConfiguration().GetSection("SwaggerCC").Value ?? string.Empty;
        }

        public static string urlSwagger2()
        {
            return GetConfiguration().GetSection("SwaggerVB").Value ?? string.Empty;
        }

        public static string urlCertLogin()
        {
            return GetConfiguration().GetSection("CertificateLogin:PublicUrl").Value ?? string.Empty;
        }
        public static HttpClient ObtenerCliente(String token, IHttpClientFactory clientFactory)
        {
            var client = clientFactory.CreateClient();
            client.BaseAddress = new Uri(Utilidades.urlSwagger());
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            return client;
        }
        public string NullDatetoString(string date)
        {
            if (date == "01/01/0001")
            {
                return "";
            }
            else {
                return date;
                    }
        }
        public static async Task<T> ObtenerObjeto<T>(HttpClient cliente, String uri)
        {
            var response = await cliente.GetAsync(uri);

            if (response.IsSuccessStatusCode)
            {
                var resultContent = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<T>(resultContent);
            }
            else
            {
                return default(T);
            }
        }
        public static async Task<T> ObtenerObjeto<T>(HttpClient cliente, String uri, Expression filtro)
        {
            var serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
            var serializedExpression = serializer.SerializeText(filtro);

            var jsonContent = JsonConvert.SerializeObject(new { Expression = serializedExpression });
            var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
            var response = await cliente.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var resultContent = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<T>(resultContent);
            }
            else
            {
                return default(T);
            }
        }
        public static async Task<T> NuevoObjeto<T>(HttpClient cliente, String uri, T objeto)
        {
            try
            {
                // Limpiar propiedades de navegación
                VaciarPropiedadesDeNavegacion(objeto);

                var response = await cliente.PostAsJsonAsync(uri, objeto);

                if (response.IsSuccessStatusCode)
                {
                    var resultContent = await response.Content.ReadAsStringAsync();
                    return JsonConvert.DeserializeObject<T>(resultContent);
                }
                else
                {
                    return default(T);
                }
            }
            catch (Exception ex)
            {
                var mess = ex.ToString();
                return default(T);
            }

        }
        public static async Task<T> ActualizarObjeto<T>(HttpClient cliente, String uri, T objeto)
        {
            try
            {
                // Limpiar propiedades de navegación
                VaciarPropiedadesDeNavegacion(objeto);

                // Realizar la solicitud PUT
                var response = await cliente.PutAsJsonAsync(uri, objeto);

                if (response.IsSuccessStatusCode)
                {
                    var resultContent = await response.Content.ReadAsStringAsync();
                    //return JsonConvert.DeserializeObject<T>(resultContent);
                    return objeto;
                }
                else
                {
                    Console.WriteLine($"Error al actualizar: {response.StatusCode}, {await response.Content.ReadAsStringAsync()}");
                    return default(T);
                }
            }
            catch (Exception ex)
            {
                var mess = ex.ToString();
                return default(T);
            }
        }
        public static async Task ExportarExcelEnBrowser<T>(IJSRuntime js,IEnumerable<T> datos,byte[] logoBytes,XLColor headerColor,string nombreFichero)
        {
            using var ms = tsDocumentos.TablaExportador
                .GenerarExcelEnMemoria(datos, logoBytes, headerColor);
            var bytes = ms.ToArray();
            var b64 = Convert.ToBase64String(bytes);
            await js.InvokeVoidAsync("saveAsFile", nombreFichero, b64);
        }
        public static async Task ExportarPdfEnBrowser<T>(IJSRuntime js,IEnumerable<T> datos,byte[] logoBytes,Color headerColor,string nombreFichero)
        {
            using var ms = tsDocumentos.TablaExportador
                .GenerarPdfEnMemoria(datos, logoBytes, headerColor);
            var bytes = ms.ToArray();
            var b64 = Convert.ToBase64String(bytes);
            await js.InvokeVoidAsync("saveAsFile", nombreFichero, b64);
        }
        // Método para limpiar las propiedades de navegación
        private static void VaciarPropiedadesDeNavegacion<T>(T objeto)
        {
            // Obtener todas las propiedades del objeto
            var propiedades = typeof(T).GetProperties();

            foreach (var propiedad in propiedades)         
            {
                var tipo = propiedad.PropertyType;

                //if (propiedad.PropertyType != Byte[]) {
                // Verificar si la propiedad es de tipo de navegación
                if (propiedad.PropertyType.IsClass && propiedad.PropertyType != typeof(string))
                    {

                    if ((tipo.IsArray && tipo.GetElementType() == typeof(byte)) || typeof(Microsoft.AspNetCore.Http.IFormFile).IsAssignableFrom(tipo))
                    {
                        continue;
                    }
                    // Vaciar la propiedad estableciéndola en null
                    if (propiedad.CanWrite)
                        {
                            propiedad.SetValue(objeto, null);
                            Console.WriteLine($"Propiedad de navegación '{propiedad.Name}' vaciada.");
                        }
                    }
                }
            //}
        }

    }

}

