using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Threading;
using ImageMagick;
using iTextSharp.text;
using iTextSharp.text.pdf;
using MySqlConnector;
using ZXing;
using Image = iTextSharp.text.Image;

namespace AsignadorKits_Almex_ML
{
   public class clsPDF
   {
      public string Base64Converter(string string_b64, string sale_order_id, string product_id, string seller_sku, int quantity, string carrier_name, int customer_id, string reference_order_number)
      {
         try
         {
            // abrimos pdf
            var reader = new PdfReader(Convert.FromBase64String(string_b64));
            var ms = new MemoryStream();
            var stamper = new PdfStamper(reader, ms);            // agregamos info adicional
            var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            float x, y;
            for (var i = 1; i <= reader.NumberOfPages; i++)
            {
               var contentByte = stamper.GetOverContent(i);
               contentByte.BeginText();
               contentByte.SetFontAndSize(baseFont, 8);
               var page = reader.GetPageSize(i);
               var algo = page.Width;
                  var algo1 = page.Height;
               switch (carrier_name)
               {
                  case "PAQUETEXPRESS":
                     x = 200;
                     y = 570;
                     break;
                  case "CARSSA":
                     x = 500;
                     y = 90;
                     break;
                  case "SENDEX":
                     x = 450;
                     y = 440;
                     break;
                  case "FEDEX":
                  case "Fedex":
                     switch (customer_id)
                     {
                        case 100:
                           x = 300;
                           y = 600;
                           break;
                        case 102:
                           x = 200;
                           y = 150;
                           break;
                        case 80:
                           x = 100;
                           y = algo1 < 450 ? 90 : 480;
                           break;
                        case 96:
                           x = 240;
                           y = 570;
                           break;
                        case 103:
                           x = 180;
                           y = 450;
                           break;
                        default:
                           x = 240;
                           y = 570;
                           break;
                     }
                     break;
                  case "Express":
                     x = 190;
                     y = 210;
                     break;
                  case "DHL  a sucursal":
                  case "Paquetexpress normal a domicilio":
                  case "FedEx Express Saver":
                  case "FedEx a sucursal":
                  case "MEL Distribution":
                     x = 170;
                     y = 360;
                     break;
                  case "ESTAFETA":
                  case "Estafeta Estándar Domicilio":
                     x = 170;
                     y = 400;
                     break;
                  case "DHL":
                     x = 230;
                     y = 300;
                     break;
                  case "REDPACK":
                     x = 200;
                     y = 350;
                     break;
                  case "1":
                     x = 200;
                     y = 50;
                     break;
                  case "99Min":
                     x = 220;
                     y = 400;
                     break;
                  case "":
                     x = 230;
                     y = 300;
                     break;
                  default:
                     x = algo > 800 ? algo - 470 : 170;
                     y = algo1 > 450 ? 660 : 90;
                     break;
               }
               contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "SO: " + sale_order_id, x, y, 0);
                  contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "Reference: " + reference_order_number, x, y+10, 0);
                  contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "SKU: " + product_id, x, y+20, 0);
                  contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, seller_sku, x, y+30, 0);
                  contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "QTY: " + quantity, x, y+40, 0);
                  contentByte.EndText();
            }
            stamper.Close();
            reader.Close();
            // salvamos nuevo documento
            // convertimos en base64
            var base64String = Convert.ToBase64String(ms.GetBuffer());
            return base64String;
         }
         catch (Exception ex)
         {
            // MsgBox("No se pudo generar guia: " & ex.Message)
            return string_b64;
         }
      }

      public void CreateMergedPDF(string targetPDF, string[] archivos, string carrier)
      {
         using (var stream = new FileStream(targetPDF, FileMode.Create))
         {
            if (string.Compare(carrier, "Estafeta", StringComparison.CurrentCultureIgnoreCase) == 0)
            {
               var pdfDoc = new Document(PageSize.LETTER);
               var pdf = new PdfCopy(pdfDoc, stream);
               pdfDoc.Open();
               foreach (var archivo in archivos)
               {
                  var images = new MagickImageCollection();
                  images.Read(Convert.FromBase64String(archivo), new MagickReadSettings
                  {
                     Density = new Density(300, 300),
                     UseMonochrome = true,
                     Compression = CompressionMethod.LZMA
                  });
                  foreach (var image in images)
                  {
                     var ms = new MemoryStream();
                     image.Write(ms, MagickFormat.Pdf);
                     pdf.AddDocument(new PdfReader(ms.GetBuffer()));
                  }
               }
               pdfDoc.Close();
            }
            else
            {
               var document = new Document();
               var copy = new PdfCopy(document, stream);
               document.Open();
               foreach (var archivo in archivos)
               {
                  var reader = new PdfReader(Convert.FromBase64String(archivo));
                  copy.AddDocument(reader);
                  reader.Close();
               }
               document.Close();
            }
         }
      }

      public string LeeCodigoBarrasDePDF(string origenBase64, string sale_order_id, int user_id)
      {
         var pdf = origenBase64;
         try
         {
            var cn = new clsConexion();
            var dtpedido = cn.TraeDataTable("SELECT customer_id, carrier_id, shipment_provider, reference_order_number, count_items, sale_order_id, tracking_number FROM sale_order_header WHERE sale_order_id=@sale_order_id", new[]
               {
                  new MySqlParameter("@sale_order_id", sale_order_id)
               }, CommandType.Text);
            var dr = dtpedido.Rows[0];
            if (int.Parse(dr["customer_id"].ToString()) == 100)
            {
               var images = new MagickImageCollection();
               images.Read(Convert.FromBase64String(origenBase64), new MagickReadSettings
               {
                  Density = new Density(300, 300),
                  UseMonochrome = true,
                  Compression = CompressionMethod.NoCompression
               });
               var pdfs = CreateSplitPDF(origenBase64, sale_order_id);
               if (int.Parse(dr["count_items"].ToString()) < 2)
               {
                  if (images.Count > 1)
                     for (int i = 0; i < images.Count; i++)
                     {
                        var ms = new MemoryStream();
                        images[i].Write(ms, MagickFormat.Png);
                        var barcodeReader = new BarcodeReader();
                        var results = barcodeReader.DecodeMultiple(new Bitmap(ms));
                        foreach (var result in results)
                        {
                           if (int.Parse(dr["carrier_id"].ToString()) == 5)
                           {
                              if (result.Text.StartsWith("JJD"))
                              {
                                 BuscaShippingLabelInfo(sale_order_id, result.Text, user_id, int.Parse(dr["carrier_id"].ToString()));
                                 InsertaBase64(sale_order_id, result.Text, pdfs[i]);
                              }
                           }
                           else // carrier 1
                           {
                              if (result.Text.Length < 100)
                              {
                                 BuscaShippingLabelInfo(sale_order_id, result.Text.Substring(22, 12), user_id, int.Parse(dr["carrier_id"].ToString()));
                                 InsertaBase64(sale_order_id, result.Text.Substring(22, 12), pdfs[i]);
                              }
                           }
                        }
                     }
               }
               else
               {
                  var dtpedidos = cn.TraeDataTable("SELECT H.customer_id, H.carrier_id, H.shipment_provider, H.reference_order_number, H.count_items, H.sale_order_id, D.quantity FROM sale_order_header H JOIN sale_order_detail D ON H.sale_order_id = D.sale_order_id WHERE H.reference_order_number LIKE '" + dr["reference_order_number"].ToString().Substring(0, dr["reference_order_number"].ToString().Length - 2) + "%' ORDER BY H.sale_order_id; ", new MySqlParameter[] { }, CommandType.Text);
                  var i = 0;
                  foreach (DataRow row in dtpedidos.Rows)
                  {
                     for (int j = 0; j < int.Parse(row["quantity"].ToString()); j++)
                     {
                        var ms = new MemoryStream();
                        images[i].Write(ms, MagickFormat.Png);
                        var barcodeReader = new BarcodeReader();
                        var results = barcodeReader.DecodeMultiple(new Bitmap(ms));
                        if (string.Compare(sale_order_id, row["sale_order_id"].ToString(),
                           StringComparison.CurrentCultureIgnoreCase) == 0)
                           pdf = Convert.ToBase64String(File.ReadAllBytes(pdfs[i]));
                        var entro = false;
                        foreach (var result in results)
                        {
                           if (int.Parse(dr["carrier_id"].ToString()) == 5)
                           {
                              if (result.Text.StartsWith("JJD"))
                              {
                                 entro = BuscaShippingLabelInfoXTrackingNumber(row["sale_order_id"].ToString(), result.Text, user_id, int.Parse(dr["carrier_id"].ToString()));
                                 InsertaBase64(row["sale_order_id"].ToString(), result.Text, pdfs[i]);
                                 if (entro)
                                    break;
                              }
                           }
                           else
                           {
                              if (result.Text.Length < 100)
                              {
                                 entro = BuscaShippingLabelInfoXTrackingNumber(row["sale_order_id"].ToString(), result.Text.Substring(22, 12), user_id, int.Parse(dr["carrier_id"].ToString()));
                                 InsertaBase64(row["sale_order_id"].ToString(), result.Text.Substring(22, 12), pdfs[i]);
                                 if (entro)
                                    break;
                              }
                           }
                        }
                        i++;
                     }
                  }
               }
            }
         }
         catch (Exception ex)
         {
            var err = ex.Message;
         }
         return pdf;
      }
      public string[] CreateSplitPDF(string origenBase64, string sale_order_id)
      {
         var archivos = new List<string>();
         try
         {
            var myPath = @"C:\MerchantExport\guias";
            var reader = new PdfReader(Convert.FromBase64String(origenBase64));
            var n = reader.NumberOfPages;
            for (var i = 1; i <= reader.NumberOfPages; i++)
            {
               var outFile = Path.Combine(myPath,sale_order_id+ "_" + i + ".pdf");
               var document = new Document(reader.GetPageSize(i));
               var writer = new PdfCopy(document, new FileStream(outFile, FileMode.Create));
               document.Open();
               var page = writer.GetImportedPage(reader, i);
               writer.AddPage(page);
               document.Close();
               writer.Close();
               archivos.Add(outFile);
               Thread.Sleep(250);
            }
         }
         catch (Exception ex)
         {
         }
         return archivos.ToArray();
      }

      public string ConviertePDFEditable(string origenBase64)
      {
         try
         {
            var stream = new MemoryStream();
            var pdfDoc = new Document(PageSize.LETTER);
            var pdf = new PdfCopy(pdfDoc, stream);
            pdfDoc.Open(); 
            var images = new MagickImageCollection();
            images.Read(Convert.FromBase64String(origenBase64), new MagickReadSettings
            {
               Density = new Density(300, 300),
               UseMonochrome = true,
               Compression = CompressionMethod.LZMA
            });
            foreach (var image in images)
            {
               var ms = new MemoryStream();
               image.Write(ms, MagickFormat.Pdf);
               pdf.AddDocument(new PdfReader(ms.GetBuffer()));
            }
            pdfDoc.Close();
            return Convert.ToBase64String(stream.GetBuffer());
         }
         catch (Exception ex)
         {
            return "0";
         }
      }

      public string AgregaImagen(string string_b64, string sale_order_id, string product_id, string seller_sku, string quantity, string carrier_name, string customer_id)
      {
         // convertimos b64 y guardamos
         var myPath = @"C:\MerchantExport\guias";
         var myFileName = sale_order_id + ".pdf";
         if (!Directory.Exists(myPath))
            Directory.CreateDirectory(myPath);
         File.WriteAllBytes(Path.Combine(myPath, myFileName), Convert.FromBase64String(string_b64));
         try
         {
            // abrimos pdf
            var reader = new PdfReader(Convert.FromBase64String(string_b64));
            var stamper = new PdfStamper(reader, new FileStream(Path.Combine(myPath, myFileName), FileMode.Create));            // agregamos info adicional
            var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            float x, y;
            for (var i = 1; i <= reader.NumberOfPages; i++)
            {
               var contentByte = stamper.GetOverContent(i);
               var page = reader.GetPageSize(i);
               var algo = page.Width;
               var algo1 = page.Height;
               var imagen = Image.GetInstance(new Uri(Path.Combine(ConfigurationManager.AppSettings["CarpetaLog"], ConfigurationManager.AppSettings["LogoRappi"])));
               imagen.SetAbsolutePosition(50,50);
               contentByte.AddImage(imagen, false);
            }
            stamper.Close();
            reader.Close();
            // salvamos nuevo documento
            // convertimos en base64
            var base64String = Convert.ToBase64String(File.ReadAllBytes(Path.Combine(myPath, myFileName)));
            Thread.Sleep(250);
            return base64String;
         }
         catch (Exception ex)
         {
            // MsgBox("No se pudo generar guia: " & ex.Message)
            return string_b64;
         }
      }

      private void BuscaShippingLabelInfo(string sale_order_id, string codigo, int user_id, int carrier_id)
      {
         var cn = new clsConexion();
         var dt = cn.TraeDataTable("SELECT * FROM shipping_label_info WHERE sale_order_id=@sale_order_id AND tracking_number=@tracking_number",
            new[]
            {
               new MySqlParameter("@sale_order_id", sale_order_id),
               new MySqlParameter("@tracking_number", codigo)
            }, CommandType.Text);
         if (dt.Rows.Count == 0)
            cn.EjecutaConsulta("INSERT INTO shipping_label_info (sale_order_id, tracking_number, carrier_name, service_type, shipment_cost, shipment_type, user_id, date_created) VALUES(" + sale_order_id + ", '" + codigo + "', '"+(carrier_id==5?"DHL":"Fedex")+ "', '" + (carrier_id == 5 ? "DHL" : "Fedex") + "', 0, 1, " + user_id + ", NOW()) ", new MySqlParameter[] { }, CommandType.Text);

      }
      private bool BuscaShippingLabelInfoXTrackingNumber(string sale_order_id, string codigo, int user_id, int carrier_id)
      {
         var cn = new clsConexion();
         var dt = cn.TraeDataTable("SELECT * FROM shipping_label_info WHERE tracking_number=@tracking_number",
            new[]
            {
               new MySqlParameter("@tracking_number", codigo)
            }, CommandType.Text);
         if (dt.Rows.Count == 0)
         {
            cn.EjecutaConsulta("INSERT INTO shipping_label_info (sale_order_id, tracking_number, carrier_name, service_type, shipment_cost, shipment_type, user_id, date_created) VALUES(" + sale_order_id + ", '" + codigo + "', '" + (carrier_id == 5 ? "DHL" : "Fedex") + "', '" + (carrier_id == 5 ? "DHL" : "Fedex") + "', 0, 1, " + user_id + ", NOW()) ", new MySqlParameter[] { }, CommandType.Text);
            return true;
         }
         return false;
      }

      private void InsertaBase64(string sale_order_id, string codigo, string archivo)
      {
         var cn = new clsConexion();
         var dt = cn.TraeDataTable("SELECT * FROM sale_order_tracking_number WHERE tracking_number=@tracking_number",
            new[]
            {
               new MySqlParameter("@tracking_number", codigo)
            }, CommandType.Text);
         cn.EjecutaConsulta(dt.Rows.Count == 0
               ? "INSERT INTO sale_order_tracking_number (sale_order_id, tracking_number, tracking_base64, date_created) VALUES (@sale_order_id, @tracking_number, @tracking_base64, NOW())"
               : "UPDATE sale_order_tracking_number SET tracking_base64=@tracking_base64 WHERE sale_order_id=@sale_order_id AND tracking_number=@tracking_number",
            new[]
            {
               new MySqlParameter("@sale_order_id", sale_order_id),
               new MySqlParameter("@tracking_number", codigo),
               new MySqlParameter("@tracking_base64",
                  Convert.ToBase64String(File.ReadAllBytes(archivo)))
            }, CommandType.Text);
      }
   }
}
