using System.Data.OleDb;
using System.Text;
using System.Text.Json;
using Download_Faturas;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace Webhook_4docs
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string IndexedFilename(string stub, string extension)
            {
                int ix = 0;
                string? filename = null;

                if (File.Exists(String.Format("{0}.{1}", stub, extension)))
                {
                    do
                    {
                        ix++;
                        filename = String.Format("{0} ({1}).{2}", stub, ix, extension);
                    } while (File.Exists(filename));
                }
                else
                {
                    filename = String.Format("{0}.{1}", stub, extension);
                }
                return filename;
            }

            var builder = WebApplication.CreateBuilder(args);
            builder.Configuration.AddJsonFile("appsettings.json");

            var connectionString = builder.Configuration.GetConnectionString("WebhookDbContext");
            string? appFolder = builder.Configuration["PathBase"];

            builder.Services.AddDbContext<WebhookDbContext>(options =>
                options.UseNpgsql(connectionString)
            );

            builder.Services.AddLogging(loggingBuilder =>
            {
                loggingBuilder.ClearProviders();
                loggingBuilder.AddConsole();
            });

            // Add services to the container.
            builder.Services.AddRazorPages();

            var app = builder.Build();

            var logger = app.Services.GetRequiredService<ILogger<Program>>();

            using (var scope = app.Services.CreateScope())
            {
                var dbContext = scope.ServiceProvider.GetRequiredService<WebhookDbContext>();
                dbContext.Database.EnsureCreated();
                dbContext.Database.Migrate();
            }

            string fatura_arquivo;
            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            
            

            app.UsePathBase(appFolder);

            app.UseRouting();

            app.UseStaticFiles();

            app.UseAuthorization();

            app.MapRazorPages();

            app.Use((context, next) =>
            {
                context.Request.PathBase = new PathString(appFolder);
                return next(context);
            });

            // Endpoint para \api
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapPatch("/api", async context =>
                {
                    
                    string requestBody;
                    using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, true, 1024, true))
                    {
                        requestBody = await reader.ReadToEndAsync();
                    }

                    var JsonBody = JsonDocument.Parse(requestBody).RootElement;
                    string CaminhoDB = "X:/Middle/Informativo Setorial/Modelo Word/BD1_dados cadastrais e faturas.accdb";

                    if (JsonBody.TryGetProperty("requestID", out _))
                    {
                        string fatura_ID = JsonBody.GetProperty("requestID").ToString();

                        JsonElement DadosJson = JsonDocument.Parse(JsonBody.GetProperty("json").ToString()).RootElement;

                        Fatura fatura = new Fatura(fatura_ID, JsonBody);

                        using (OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + CaminhoDB + ";Jet OLEDB:Database Password=gds21"))
                        {
                            conn.Open();

                            fatura.Processar(conn);
                        }

                        bool t = false;

                        string? status = fatura.Status;

                        int status_id = 0;

                        switch (status)
                        {
                            case ("FATURA DUPLICADA NO BD"):
                                status_id = 4;
                                break;
                            case ("UNIDADE CONSUMIDORA NÃO LOCALIZADA NO BD"):
                                status_id = 5;
                                break;
                            case ("FATURA INCLUIDA NO BD"):
                                status_id = 6;
                                break;
                            case (_):
                                status = "ERRO";
                                status_id = 7;
                                break;
                        }

                        try
                        {
                            string path = $@"X:\Middle\Carteira {fatura.Gestao![0]}\Carteira {fatura.Gestao}\Faturas fourdocs\{status_id} - {status}";
                            System.IO.Directory.CreateDirectory(path);
                            fatura_arquivo = IndexedFilename($@"{path}\ID {fatura_ID!} -  Mês {fatura.Mes} -  Empresa {fatura.Empresa} -  Unidade {fatura.Unidade}", "pdf");
                            t = CriarArquivo(fatura_arquivo, JsonBody.GetProperty("pdfFile").ToString());

                            var DatabaseModel = new ProcessedInvoices
                            {
                                InvoiceId = Int32.Parse(fatura_ID),
                                DateTimeProcessed = DateTime.UtcNow,
                                Status = status,
                                InvoicePath = fatura_arquivo
                            };

                            logger.LogInformation("Fatura incluída no BD");

                            using (var scope = app.Services.CreateScope())
                            {
                                var dbContext = scope.ServiceProvider.GetRequiredService<WebhookDbContext>();
                                dbContext.ProcessedInvoices.Add(DatabaseModel);
                                await dbContext.SaveChangesAsync();
                            }

                            logger.LogInformation("Fatura salva na pasta " + fatura_arquivo);
                        }
                        catch
                        {
                            t = false;
                            logger.LogError("Erro no processamento da fatura");
                        }
                        
                    }
                    else if (JsonBody.TryGetProperty("healthy", out _) && JsonBody.TryGetProperty("blame", out _) && JsonBody.TryGetProperty("locationID", out _))
                    {
                        double errorID = 0;

                        switch (JsonBody.GetProperty("healthy").GetBoolean(), JsonBody.GetProperty("blame").ToString())
                        {
                            case (false, "user"):
                                logger.LogError("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " Sem acesso");
                                errorID = 1;
                                break;
                            case (false, "system"):
                                logger.LogError("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " Com erro de sistema");
                                errorID = 2;
                                break;
                            case (false, _):
                                logger.LogError("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " Com erro " + JsonBody.GetProperty("blame").ToString());
                                errorID = 3;
                                break;
                            case (true, _):
                                logger.LogInformation("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " está saudável");
                                break;
                        }

                        UpdateErrorIdStatus(CaminhoDB, JsonBody.GetProperty("locationID").GetInt64(), errorID);

                    }
                });
            });
            app.Run();
        }
        public static void UpdateErrorIdStatus(string CaminhoDB, double location_id, double errorID)
        {
            using (OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + CaminhoDB + ";Jet OLEDB:Database Password=gds21"))
            {
                conn.Open();

                using (OleDbCommand cmd = new OleDbCommand($"UPDATE AgVirtual4Docs SET AgVirtual4Docs.errorID = {errorID}\r\nWHERE (((AgVirtual4Docs.location_id)={location_id}));\r\n", conn))
                {
                    //cmd.Parameters.AddWithValue("@location_id", location_id);
                    //cmd.Parameters.AddWithValue("@errorID", errorID);
                    int test = cmd.ExecuteNonQuery();
                }
                using (OleDbCommand cmd = new OleDbCommand($"SELECT location_id, errorID FROM AgVirtual4Docs WHERE location_id = @location_id", conn))
                {
                    cmd.Parameters.AddWithValue("@location_id", location_id);
                    using (OleDbDataReader reader = cmd.ExecuteReader())
                    {
                        while(reader.Read())
                        {
                            string? test = reader["errorID"].ToString();
                        }
                    }
                }
            }
        }
        public static bool CriarArquivo(string fatura_arquivo, string pdfFile64)
        {
            //string fatura_arquivo = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test.pdf";
            bool t = false;
            if (!File.Exists(fatura_arquivo))
            {
                byte[] bytes = Convert.FromBase64String(pdfFile64);

                System.IO.FileStream stream = new FileStream(fatura_arquivo, FileMode.CreateNew);
                System.IO.BinaryWriter writer =
                    new BinaryWriter(stream);
                writer.Write(bytes, 0, bytes.Length);
                writer.Close();
                t = true;
            }
            return t;
        }
    }
}