namespace Download_Faturas
{
    using System.Data.OleDb;
    using System.Globalization;
    using System.Net.Http.Headers;
    using System.Reflection;
    using System.Reflection.Metadata.Ecma335;
    using System.Runtime.Intrinsics.X86;
    using System.Text;
    using System.Text.Json;
    using System.Text.RegularExpressions;
    using Compliance;
    using iText.Kernel.Pdf;
    using iText.Kernel.Utils;

    public class Fatura
    {
        private const string Token = "UFY4VWzqcHYcGNd0gkBOMFL9G5ZThV6gXBQIJ79F5HSqITzavz4Fe7iXvAbJLvZJ";
        private JsonElement faturaParsed;
        private string? id;
        private string? uc;
        private int? pagina;

        public Fatura(string id, string fatura_path, HttpClient httpClient)
        {
            // Utilizado para gerar novo token
            // this.token = Req_token(httpClient).ToString();
            HttpResponseMessage fatura_response = this.GetStatus(httpClient, Token, id);
            if (fatura_response.IsSuccessStatusCode)
            {
                this.faturaParsed = JsonDocument.Parse(fatura_response.Content.ReadAsStringAsync().Result).RootElement;
                this.Agrupada = this.faturaParsed.TryGetProperty("multiple", out var _);
                this.Status = this.faturaParsed.GetProperty("status").GetString();
                this.Arquivo = new FileInfo(fatura_path);
                this.id = id;

                if (this.faturaParsed.GetProperty("external").GetString() is not null)
                {
                    this.pagina = JsonDocument.Parse(this.faturaParsed.GetProperty("external").GetString() !).RootElement.GetProperty("origin")[0].GetProperty("page").GetInt32();
                }

                if (this.Agrupada)
                {
                    this.Agrupada_children = this.faturaParsed.GetProperty("children").EnumerateArray();
                }
            }
        }

        public Fatura(string id, JsonElement fatura_Parsed)
        {
            // Utilizado para gerar novo token
            // this.token = Req_token(httpClient).ToString();
            this.faturaParsed = fatura_Parsed;
            this.Agrupada = false;
            this.id = id;
        }

        public string? Gestao { get; private set; }

        public string? Empresa { get; private set; }

        public string? Unidade { get; private set; }

        public int? Mes { get; private set; }

        public string? Status { get; private set; }

        public FileInfo? Arquivo { get; private set; }

        public DirectoryInfo? PastaTUSD { get; private set; }

        public bool Agrupada { get; private set; }

        public JsonElement.ArrayEnumerator Agrupada_children { get; private set; }

        public void Processar(OleDbConnection conn)
        {
            // Variavel para armazenar os dados a serem lancados para a TUSD no BD
            RecordSet dadosTusd = new ();

            // Resultado da fatura processada
            JsonElement a;
            if (!this.faturaParsed.TryGetProperty("result", out a))
            {
                this.faturaParsed.TryGetProperty("json", out a);
            }

            // var val = a.ToString().Contains("\"measured\": [");
            Rootobject parsedResult = JsonSerializer.Deserialize<Rootobject>(a) !;
            dadosTusd.Mes = int.Parse(parsedResult.dates.reading.periodUntil.AddDays(-15).ToString("yMM"));

            string uc = new Regex("^0+").Replace(parsedResult.locationNumber, string.Empty).Replace("/", string.Empty).Replace("-", string.Empty).Replace(".", string.Empty);

            // Vinculo da fatura com os dados cadastrais
            int? unidades;
            string sqlQuery = $"SELECT COUNT (Cod_Smart_unidade) FROM Dados_cadastrais WHERE Codigo_Instalacao = @uc";
            using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
            {
                cmd.Parameters.AddWithValue("@uc", uc);

                unidades = (int?)cmd.ExecuteScalar();

                if (unidades == 1)
                {
                    sqlQuery = $"SELECT Cod_Smart_unidade, Gestao, Cliente, Unidade, PerfilCCEE, Submercado, Status_unidade, Grupo, Perfil, Distribuidora, ICMS_TUSD, Demanda_P, Demanda_FP, Caminho_NFs, Data_de_Migracao FROM Dados_cadastrais WHERE Codigo_Instalacao = @uc";
                }
                else
                {
                    sqlQuery = $"SELECT Cod_Smart_unidade, Gestao, Cliente, Unidade, PerfilCCEE, Submercado, Status_unidade, Grupo, Perfil, Distribuidora, ICMS_TUSD, Demanda_P, Demanda_FP, Caminho_NFs, Data_de_Migracao FROM Dados_cadastrais WHERE (CNPJ_CPF LIKE @cnpj AND  Codigo_Instalacao = @uc) OR (Razao_Social LIKE @razao_social AND  Codigo_Instalacao = @uc)";
                }
            }

            using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
            {
                if (unidades == 1)
                {
                    cmd.Parameters.AddWithValue("@uc", uc);
                }
                else
                {
                    cmd.Parameters.AddWithValue("@cnpj", parsedResult.customer.cnpj?[..8] != null ? parsedResult.customer.cnpj?[..8] + "%" : "NAN");
                    cmd.Parameters.AddWithValue("@uc", uc);
                    cmd.Parameters.AddWithValue("@razao_social", parsedResult.customer.name);
                }

                using (OleDbDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        // Dados cadastrais
                        dadosTusd.Cod_Smart_unidade = long.Parse(reader["Cod_Smart_unidade"].ToString() !);
                        dadosTusd.Perfil_CliqCCEE = reader["PerfilCCEE"].ToString();
                        dadosTusd.Submercado = reader["Submercado"].ToString();
                        DateTime dataMigração = DateTime.Parse(reader["Data_de_Migracao"].ToString() !);
                        if (int.Parse(dataMigração.ToString("yMM")) <= dadosTusd.Mes)
                        {
                            dadosTusd.Ambiente = reader["Status_unidade"].ToString();
                        }
                        else
                        {
                            dadosTusd.Ambiente = "Cativo";
                        }

                        dadosTusd.Grupo = reader["Grupo"].ToString();
                        dadosTusd.Distribuidora = reader["Distribuidora"].ToString();
                        dadosTusd.ICMS = float.Parse(reader["ICMS_TUSD"].ToString() !);
                        dadosTusd.Dem_Cont_P = float.Parse(reader["Demanda_P"].ToString() !);
                        dadosTusd.Dem_Cont_FP = float.Parse(reader["Demanda_FP"].ToString() !);
                        dadosTusd.Perfil = reader["Perfil"].ToString();
                        this.PastaTUSD = new DirectoryInfo(reader["Caminho_NFs"].ToString() !.Replace("\\NFe", string.Empty, StringComparison.OrdinalIgnoreCase) + "\\TUSD");
                        this.Gestao = reader["Gestao"].ToString();
                        this.Empresa = reader["Cliente"].ToString();
                        this.Unidade = reader["Unidade"].ToString();
                    }
                }
            }

            // Verifica se a fatura ja foi lançada
            bool tusdLanc;

            sqlQuery = $"SELECT Cod_TUSD FROM Dados_TUSD WHERE Cod_TUSD = ?";
            using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
            {
                double cod_tusd = double.Parse(dadosTusd.Cod_Smart_unidade.ToString() + dadosTusd.Mes.ToString());
                cmd.Parameters.AddWithValue("?", cod_tusd);

                using (OleDbDataReader reader = cmd.ExecuteReader())
                {
                    tusdLanc = reader.HasRows;
                }
            }

            if (dadosTusd.Cod_Smart_unidade == 0)
            {
                this.Status = "UNIDADE CONSUMIDORA NÃO LOCALIZADA NO BD";
                this.uc = uc;
                this.Mes = dadosTusd.Mes;
            }
            else if (tusdLanc)
            {
                this.Status = "FATURA DUPLICADA NO BD";
                this.uc = uc;
                this.Mes = dadosTusd.Mes;
            }
            else
            {
                // PIS e Cofins
                sqlQuery = $"SELECT Distribuidoras_PIS.PIS, Distribuidoras_PIS.COFINS FROM Distribuidoras_geral INNER JOIN Distribuidoras_PIS ON Distribuidoras_geral.ID_dist = Distribuidoras_PIS.ID_dist WHERE Distribuidoras_PIS.Mes = ? AND Distribuidoras_geral.Distribuidora = ?";

                using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                {
                    cmd.Parameters.AddWithValue("?", dadosTusd.Mes.ToString());
                    cmd.Parameters.AddWithValue("?", dadosTusd.Distribuidora);

                    using (OleDbDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            // PIS e Cofins
                            dadosTusd.PIS = float.Parse(reader["PIS"].ToString() !);
                            dadosTusd.COFINS = float.Parse(reader["COFINS"].ToString() !);
                        }
                    }
                }

                // Dados da fatura processada
                dadosTusd.Cod_TUSD = long.Parse(dadosTusd.Cod_Smart_unidade.ToString() + dadosTusd.Mes.ToString());
                switch (parsedResult.tariffModality, parsedResult.subgroup)
                {
                    case ("blue", _):
                        dadosTusd.Perfil = "AZUL";
                        break;

                    case ("green", _):
                        dadosTusd.Perfil = "VERDE";
                        break;

                    case ("standart", _):
                        dadosTusd.Perfil = "CONVENCIONAL";
                        break;

                    case (_, "B3"):
                        dadosTusd.Perfil = "CONVENCIONAL";
                        break;

                    default:
                        break;
                }

                dadosTusd.Valor = parsedResult.totalCharges;
                dadosTusd.Inicio_Leitura = parsedResult.dates.reading.periodFrom;
                dadosTusd.Fim_leitura = parsedResult.dates.reading.periodUntil;
                DateTime d = DateTime.Now;
                dadosTusd.Hora_TUSD = new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second);
                dadosTusd.Dem_Reativa_kvar = 0;
                dadosTusd.Multa = 0;
                dadosTusd.Credito = 0;
                dadosTusd.Bandeira_RS_MWh = 0;
                dadosTusd.FIC_DIC = 0;
                dadosTusd.Enc_conexao = 0;
                dadosTusd.Liminar_ICMS = 0;
                dadosTusd.Outros = 0;
                dadosTusd.Cred_livre = 0;
                dadosTusd.Tempo_TUSD = 0;
                dadosTusd.Lanc_aut = true;
                dadosTusd.Rev_atual = true;
                dadosTusd.Revisao = 0;

                // Loop entre os dados faturados na fatura
                int j = 0;
                float? dem_Reg_P = null;
                float? dem_Reg_FP = null;
                float? consumo_Reg_FP = 0;
                string? kind_P = string.Empty;
                string? kind_FP = string.Empty;

                if (this.id == "2356193")
                {
                    int i = 0;
                    i++;
                }

                List<(string, float)> insertOthers = new List<(string, float)>();
                foreach (Item item in parsedResult.items)
                {
                    switch (item.type, item.period)
                    {
                        // Energia Ponta
                        case ("energy", "peak"):
                            if (kind_P == string.Empty)
                            {
                                kind_P = item.kind;
                            }

                            if (item.kind == kind_P)
                            {
                                dadosTusd.Consumo_P = dadosTusd.Consumo_P + (item.billed / 1000);
                            }

                            break;

                        // Energia Fora de Ponta
                        case ("energy", _):
                            if (item.period == "off-peak" || item.period == "off-peak inductive" || item.period == "off-peak capacitive" || item.period == "reserved")
                            {
                                if (kind_FP == string.Empty)
                                {
                                    kind_FP = item.kind;
                                }

                                if (item.kind == kind_FP)
                                {
                                    dadosTusd.Consumo_FP = dadosTusd.Consumo_FP + (item.billed / 1000);
                                }
                            }
                            else
                            {
                                insertOthers.Add((item.texts[0], item.charge));
                            }

                            break;

                        // Demanda
                        case ("demand", _):

                            if (item.contract != 0)
                            {
                                if (item.period == "peak")
                                {
                                    dadosTusd.Dem_Reg_P = item.billed;
                                    dadosTusd.Dem_Cont_P = item.contract;
                                }
                                else if (item.period == "off-peak")
                                {
                                    dadosTusd.Dem_Reg_FP = item.billed;
                                    dadosTusd.Dem_Cont_FP = item.contract;
                                }

                                if (dadosTusd.Perfil == "AZUL")
                                {
                                    if (item.period == "peak")
                                    {
                                        sqlQuery = $"UPDATE Dados_cadastrais SET Demanda_P = @demanda WHERE Cod_Smart_unidade = @cod_smart_unidade";
                                        using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                                        {
                                            cmd.Parameters.AddWithValue("@demanda", item.contract);
                                            cmd.Parameters.AddWithValue("@cod_smart_unidade", dadosTusd.Cod_Smart_unidade);
                                            cmd.ExecuteNonQuery();
                                        }
                                    }
                                    else if (item.period == "off-peak")
                                    {
                                        sqlQuery = $"UPDATE Dados_cadastrais SET Demanda_FP = @demanda WHERE Cod_Smart_unidade = @cod_smart_unidade";
                                        using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                                        {
                                            cmd.Parameters.AddWithValue("@demanda", item.contract);
                                            cmd.Parameters.AddWithValue("@cod_smart_unidade", dadosTusd.Cod_Smart_unidade);
                                            cmd.ExecuteNonQuery();
                                        }
                                    }
                                }
                                else if (dadosTusd.Perfil == "VERDE")
                                {
                                    sqlQuery = $"UPDATE Dados_cadastrais SET Demanda_P = @demanda, Demanda_FP = @demanda WHERE Cod_Smart_unidade = @cod_smart_unidade";
                                    using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                                    {
                                        cmd.Parameters.AddWithValue("@demanda", item.contract);
                                        cmd.Parameters.AddWithValue("@cod_smart_unidade", dadosTusd.Cod_Smart_unidade);
                                        cmd.ExecuteNonQuery();
                                    }
                                }
                            }

                            break;

                        // Ilum. publica
                        case ("publicLighting", _):
                            dadosTusd.Ilum_Publica = item.charge;
                            break;

                        // Energia Reativa
                        case ("excessReactiveEnergy", _):
                            dadosTusd.En_Reativa_Mvarh += item.billed / 1000;
                            break;

                        // Demanda Reativa
                        case ("excessReactiveDemand", _):
                            dadosTusd.Dem_Reativa_kvar += item.billed;
                            break;

                        // Bandeira Tarifaria
                        case ("flagSurcharge", _):
                            dadosTusd.Bandeira_RS_MWh = item.charge;
                            break;

                        // Items não classificados
                        case ("other", _):
                            j++;

                            // Exclui os items lançados anteriormente para a fatura e cria a instrução SQL para inserir os novos items
                            if (j == 1)
                            {
                                sqlQuery = $"DELETE FROM Dados_TUSD_aux WHERE Cod_TUSD = @cod_tusd";
                                using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                                {
                                    cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);
                                    cmd.ExecuteNonQuery();
                                }
                            }

                            insertOthers.Add((item.name, item.charge));
                            break;
                    }
                }

                // Busca a demanda registrada nos itens medidos
                foreach (Measureditem measuredItem in parsedResult.measuredItems)
                {
                    switch (measuredItem.type, measuredItem.period)
                    {
                        case ("demand", "peak"):
                            dem_Reg_P = measuredItem.measured.Max();
                            break;
                        case ("demand", "off-peak"):
                            dem_Reg_FP = measuredItem.measured.Max();
                            break;
                        case ("energy", "off-peak"):
                            consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured.Sum();
                            break;
                        case ("energy", "off-peak inductive"):
                            consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured.Sum();
                            break;
                        case ("energy", "off-peak capacitive"):
                            consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured.Sum();
                            break;
                        case ("energy", "off-peak capacitive green flag"):
                            consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured.Sum();
                            break;
                        case ("energy", "off-peak inductive green flag"):
                            consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured.Sum();
                            break;
                        case ("energy", "reserved"):
                            consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured.Sum();
                            break;
                    }
                }

                if (dem_Reg_P != null && (Math.Round((decimal)dadosTusd.Consumo_FP, 2) == Math.Round((decimal)(consumo_Reg_FP * 1.025 / 1000) !, 2)))
                {
                    dadosTusd.Dem_Reg_P = (float)(dem_Reg_P * 1.025);
                }
                else if (dem_Reg_P != null)
                {
                    dadosTusd.Dem_Reg_P = (float)dem_Reg_P;
                }

                if (dem_Reg_FP != null && (Math.Round((decimal)dadosTusd.Consumo_FP, 2) == Math.Round((decimal)(consumo_Reg_FP * 1.025 / 1000) !, 2)))
                {
                    dadosTusd.Dem_Reg_FP = (float)(dem_Reg_FP * 1.025);
                }
                else if (dem_Reg_FP != null)
                {
                    dadosTusd.Dem_Reg_FP = dem_Reg_FP ?? 0;
                }

                var dados = dadosTusd.GetType().GetProperties();
                StringBuilder fields = new StringBuilder();
                StringBuilder values = new StringBuilder();

                // Verifica se já existe a fatura lançada | atualizar fatura ou nova fatura
                if (tusdLanc)
                {
                    // Cria o comando para atualização da fatura
                    sqlQuery = "UPDATE Dados_TUSD SET ";

                    // Loop por todos os dados ja obtidos
                    PropertyInfo[] propriedades = typeof(RecordSet).GetProperties();
                    foreach (PropertyInfo propriedade in propriedades)
                    {
                        string nomeColuna = propriedade.Name;

                        // Adicione a coluna à instrução SQL
                        sqlQuery += $"{nomeColuna} = @{nomeColuna}, ";
                    }

                    // Remova a última vírgula e adicione a cláusula WHERE
                    sqlQuery = sqlQuery.TrimEnd(',', ' ') + $" WHERE Cod_TUSD = @cod_tusd";

                    using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                    {
                        foreach (PropertyInfo propriedade in propriedades)
                        {
                            string nomeColuna = propriedade.Name;
                            object valorColuna = propriedade.GetValue(dadosTusd) ?? string.Empty;
                            cmd.Parameters.AddWithValue($"@{nomeColuna}", valorColuna);
                        }

                        // Valor do código TUSD na cláusula WHERE
                        cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);

                        cmd.ExecuteNonQuery();
                    }

                    // Inseri os itens classificados como "othes" após criar o registro da TUSD devido as relação entre as tabelas
                    foreach ((string name, float valor) in insertOthers)
                    {
                        j++;
                        sqlQuery = "INSERT INTO Dados_TUSD_aux (Cod_TUSD,Id,Nome,Valor,Cod_lanc) VALUES (@cod_tusd, @j, @name, @valor,0)";
                        using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                        {
                            cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);
                            cmd.Parameters.AddWithValue("@j", j);
                            cmd.Parameters.AddWithValue("@name", name);
                            cmd.Parameters.AddWithValue("@valor", valor);
                            cmd.ExecuteNonQuery();
                        }
                    }
                }
                else
                {
                    // Cria o comando para lançar da fatura
                    sqlQuery = "INSERT INTO Dados_TUSD (";

                    PropertyInfo[] propriedades = typeof(RecordSet).GetProperties();
                    /*int i = 0;*/
                    foreach (PropertyInfo propriedade in propriedades)
                    {
                        string nomeColuna = propriedade.Name;

                        // Adicione a coluna à instrução SQL
                        sqlQuery += $"{nomeColuna}, ";
                    }

                    // Remova a última vírgula e adicione a cláusula VALUES
                    sqlQuery = sqlQuery.TrimEnd(',', ' ') + ") VALUES (";

                    foreach (PropertyInfo propriedade in propriedades)
                    {
                        // Adicione os parâmetros à instrução SQL
                        string nomeColuna = propriedade.Name;
                        sqlQuery += $"@{nomeColuna}, ";
                    }

                    // Remova a última vírgula e feche a instrução SQL
                    sqlQuery = sqlQuery.TrimEnd(',', ' ') + ")";

                    using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                    {
                        foreach (PropertyInfo propriedade in propriedades)
                        {
                            string nomeColuna = propriedade.Name;
                            object valorColuna = propriedade.GetValue(dadosTusd) ?? string.Empty;
                            cmd.Parameters.AddWithValue($"@{nomeColuna}", valorColuna);
                        }

                        cmd.ExecuteNonQuery();
                    }

                    // Inseri os itens classificados como "othes" após criar o registro da TUSD devido as relação entre as tabelas
                    j = 0;
                    foreach ((string name, float valor) in insertOthers)
                    {
                        j++;
                        sqlQuery = "INSERT INTO Dados_TUSD_aux (Cod_TUSD,Id,Nome,Valor,Cod_lanc) VALUES (@cod_tusd, @j, @name, @valor, 0)";
                        using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
                        {
                            cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);
                            cmd.Parameters.AddWithValue("@j", j);
                            cmd.Parameters.AddWithValue("@name", name);
                            cmd.Parameters.AddWithValue("@valor", valor);
                            cmd.ExecuteNonQuery();
                        }
                    }
                }

                this.Status = "FATURA INCLUIDA NO BD";
                this.uc = uc;
                this.Mes = dadosTusd.Mes;
            }
        }

        public void Mover(bool separar)
        {
            string destino = string.Empty;

            switch (this.Status, separar)
            {
                case ("UNIDADE CONSUMIDORA NÃO LOCALIZADA NO BD", _):

                    destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\5 - {this.Status}\ID {this.id!} -  Mês {this.Mes} -  UC {this.uc}.pdf";

                    if (separar)
                    {
                        new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
                        this.Arquivo = new FileInfo(destino);
                    }
                    else
                    {
                        try
                        {
                            this.Arquivo!.MoveTo(destino);
                        }
                        catch
                        {
                        }
                    }

                    break;

                case ("FATURA DUPLICADA NO BD", _):

                    destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\4 - {this.Status}\ID {this.id!} -  Mês {this.Mes} -  Empresa {this.Empresa} -  Unidade {this.Unidade}.pdf";

                    if (separar)
                    {
                        new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
                        this.Arquivo = new FileInfo(destino);
                    }
                    else
                    {
                        try
                        {
                            this.Arquivo!.MoveTo(destino);
                        }
                        catch
                        {
                        }
                    }

                    break;

                case ("FATURA INCLUIDA NO BD", _):

                    if (this.PastaTUSD!.Exists)
                    {
                        destino = this.PastaTUSD!.FullName + $@"\ID {this.id!} -  Mês {this.Mes} -  Empresa {this.Empresa} -  Unidade {this.Unidade}.pdf";
                    }
                    else
                    {
                        destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\6 - {this.Status}\ID {this.id!} -  Mês {this.Mes} -  Empresa {this.Empresa} -  Unidade {this.Unidade}.pdf";
                    }

                    if (separar)
                    {
                        new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
                        this.Arquivo = new FileInfo(destino);
                    }
                    else
                    {
                        try
                        {
                            this.Arquivo!.MoveTo(destino);
                        }
                        catch
                        {
                        }
                    }

                    break;

                case ("INVALID", _):

                    destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\7 - ERRO\ID {this.id!} - {this.Arquivo?.Name}";

                    if (separar)
                    {
                        new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
                        this.Arquivo = new FileInfo(destino);
                    }
                    else
                    {
                        try
                        {
                            this.Arquivo!.MoveTo(destino);
                        }
                        catch
                        {
                            throw;
                        }
                    }

                    break;

                case (_, true):

                    destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\3 - PROCESSANDO\ID {this.id!} - {this.Arquivo?.Name}";

                    new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
                    this.Arquivo = new FileInfo(destino);
                    break;
            }
        }

        private HttpResponseMessage GetStatus(HttpClient httpClient, string token, string id)
        {
            var request = new HttpRequestMessage(new HttpMethod("GET"), $"https://api.4docs.cloud/v2/request/status?id={id}");
            request.Headers.TryAddWithoutValidation("Authorization", $"Bearer {token}");
            var response = httpClient.Send(request);
            return response;
        }

        private string Req_token(HttpClient httpClient)
        {
            var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.4docs.cloud/v2/oauth2/token");
            var base64authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes("smart:vnqtvmesikjzyipc"));
            request.Headers.TryAddWithoutValidation("Authorization", $"Basic {base64authorization}");
            request.Content = new StringContent("grant_type=client_credentials");
            request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
            var response = httpClient.Send(request);
            return JsonDocument.Parse(response.Content.ReadAsStringAsync().Result).RootElement.GetProperty("access_token").GetString() !;
        }
    }

    public class PDFSplitter
    {
        public PDFSplitter(int? pagina, string origem, string destino)
        {
            FileStream document = new FileStream(origem, FileMode.Open, FileAccess.Read, FileShare.Read);
            PdfDocument pdfDocument = new PdfDocument(new PdfReader(document));
            var split = new CustomPdfSplitter(pdfDocument, pageRange => new PdfWriter(destino));
            PdfDocument result = split.ExtractPageRange(new PageRange(pagina.ToString()));
            document.Close();
            result.Close();
        }
    }

    public class CustomPdfSplitter : PdfSplitter
    {
        private Func<PageRange, PdfWriter> nextWriter;

        public CustomPdfSplitter(PdfDocument pdfDocument, Func<PageRange, PdfWriter> nextWriter)
            : base(pdfDocument)
        {
            this.nextWriter = nextWriter;
        }

        protected override PdfWriter GetNextPdfWriter(PageRange documentPageRange)
        {
            return this.nextWriter.Invoke(documentPageRange);
        }
    }
}