using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using CommerceApp.Files;
using CommerceApp.Orders;
using CommerceApp.Orders.Dtos;
using CommerceApp.Prints;
using CommerceApp.Prints.Dtos;
using DinkToPdf;
using DinkToPdf.Contracts;
using HandlebarsDotNet;
using HandlebarsDotNet.Extension.Json;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
using Newtonsoft.Json;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using Scriban;
using Scriban.Runtime;

[ApiController]
public class ScryberController : ControllerBase
{
    private IConverter _converter;
    public PrintDocumentDto ViewModel { get; set; }
    private readonly IFileAppService _fileAppService;
    public IDocumentAppService _documentAppService { get; set; }
    private readonly IWebHostEnvironment _webHostEnvironment;

    private readonly ITemplateAppService _templateAppService;
    Dictionary<string, string> documentTypes = new Dictionary<string, string>();
    public ScryberController(IConverter converter, IWebHostEnvironment webHostEnvironment, IDocumentAppService documentAppService, IFileAppService fileAppService, ITemplateAppService templateAppService)
    {
        _converter = converter;
        _webHostEnvironment = webHostEnvironment;
        _documentAppService = documentAppService;
        documentTypes.Add("Facture", "facture");
        documentTypes.Add("SalesQuote", "Devis");
        documentTypes.Add("SalesOrder", "Bon de commande");
        documentTypes.Add("SalesInvoice", "Facture");
        documentTypes.Add("SalesDelivery", "Bon de livraison");
        documentTypes.Add("SalesReturn", "Bon de retour");
        documentTypes.Add("SalesCreditNote", "Avoir");
        documentTypes.Add("Purchases", "Achats");
        documentTypes.Add("PurchaseQuote", "Demande d'achat");
        documentTypes.Add("PurchaseOrder", "Bon de commande");
        documentTypes.Add("PurchaseInvoices", "Facture");
        documentTypes.Add("PurchaseDelivery", "Bon de réception");
        documentTypes.Add("PurchaseReturn", "Bon de retour");
        documentTypes.Add("PurchaseCreditNote", "Avoir");
        _fileAppService = fileAppService;
        _templateAppService = templateAppService;
    }
    [HttpGet]
    [Route("scryper/test1")]
    public async Task<IActionResult> HelloWorld(Guid id)
    {

        ViewModel = await _documentAppService.GetPrintDocumentAsync(id);

        // Create a Scriban template context and set the entity name
        var templateContext = new TemplateContext();
        var scriptObject = new ScriptObject();
        scriptObject.Import(ViewModel, renamer: member => member.Name);
        templateContext.PushGlobal(scriptObject);

        // Render the template
        var renderedController = Template.Parse(GetHTMLString("facture")).Render(templateContext);


        var globalSettings = new GlobalSettings
        {
            ColorMode = ColorMode.Color,
            Orientation = Orientation.Portrait,
            PaperSize = PaperKind.A4,
            Margins = new MarginSettings { Top = 10, Bottom = 10 },
            DocumentTitle = "PDF Report"
        };
        var objectSettings = new ObjectSettings
        {
            PagesCount = true,
            HtmlContent = renderedController,
            WebSettings = { DefaultEncoding = "utf-8", },
            // HeaderSettings = { FontName = "Arial", FontSize = 9, Right = "Page [page] of [toPage]", Line = true },
            FooterSettings = { HtmUrl = $"{this._webHostEnvironment.WebRootPath}//templates//footer.html" },
        };
        var pdf = new HtmlToPdfDocument()
        {
            GlobalSettings = globalSettings,
            Objects = { objectSettings }
        };
        var file = _converter.Convert(pdf);
        return File(file, "application/pdf");
    }
    [NonAction]
    public string GetHTMLString(string fileName)
    {


        var text = System.IO.File.ReadAllText($"{this._webHostEnvironment.WebRootPath}//templates//{fileName}.html");
        return text;
    }
 
    [NonAction]
    public string GetHtmlText(string path)
    {

        return System.IO.File.ReadAllText(path);
    }
    [NonAction]
    public string GetFooterText()
    {
        var text = $"{ViewModel.Company.CompanyName}<br/>" +
                    $"RC : {ViewModel.Company.TaxIdentification} - PATENTE :{ViewModel.Company.Patente} - IF : {ViewModel.Company.TaxIdentification} -  ICE :{ViewModel.Company.ICE} <br/>" +
                    //  $"{ViewModel.Company.Address1} <br/>" +
                    // $"{ViewModel.Company.Address2} <br/> +
                    $"Téléphone: {ViewModel.Company.PhoneNumber} - Email: {ViewModel.Company.Email} - Site web: {ViewModel.Company.Email}";
        return text;
    }


    
    [HttpGet]
    [Route("print/invoice/{invoiceId}/{docType}/{templateId}")]
    public async Task<IActionResult> PrintAsync(string invoiceId, string docType, Guid templateId)
    {

        ViewModel = await _documentAppService.GetPrintDocumentAsync(Guid.Parse(invoiceId));
        ViewModel.DocumentType = documentTypes[docType];
        var templateModels = await _templateAppService.GetAsync(templateId);


        dynamic settingsObject = System.Text.Json.JsonSerializer.Deserialize<dynamic>(templateModels.CssCustomization);
        dynamic settings = JsonConvert.DeserializeObject<dynamic>(templateModels.CssCustomization);

        ViewModel.Settings = settingsObject;

        var fileDto = await _fileAppService.GetBlobAsync(new GetBlobRequestDto { Name = ViewModel.Company.Id.ToString() });
        if (ViewModel.Company.Id != Guid.Empty)
            ViewModel.Company.LogoBase = Convert.ToBase64String(fileDto.Content);


        var handlebars = Handlebars.Create();
        handlebars.Configuration.UseJson();

        string htmlTemplate = GetHtmlText($"{this._webHostEnvironment.WebRootPath}//templates//{docType}//standard.html");
        var template = handlebars.Compile(htmlTemplate);
        var htmlContent = template(ViewModel);

        var footerTemplate =handlebars.Compile(templateModels.FooterContent.Replace("\n", "<br/>"));
        var footerContent = footerTemplate(ViewModel);

        footerContent =$"<div style='text-align: center; color: {settings.footerFontColor};font-size: {settings.footerFontSize}pt;'>{footerContent}</div>";
        
        // Path to the wkhtmltopdf executable
        string wkhtmltopdfPath = "/usr/local/bin/wkhtmltopdf";

        // Path to the HTML file containing the footer content
        string footerFilePath = $"{this._webHostEnvironment.WebRootPath}//templates//footer.html";
        // Header HTML content
        string headerHtml = "<html><body><div style='text-align: center;'>Header Content</div></body></html>";

        int marginTop = settings.marginTop;
        int marginBottom = settings.marginBottom;
        int marginLeft = settings.marginLeft;
        int marginRight = settings.marginRight;
        // Create a new process for running the wkhtmltopdf command
        var processStartInfo = new ProcessStartInfo()
        {
            FileName = wkhtmltopdfPath,
            Arguments = $"--quiet --encoding \"utf-8\" --disable-smart-shrinking --footer-html \"{footerFilePath}\" --margin-bottom {marginBottom} --margin-left 0 --margin-right 0 --margin-top {marginTop} --replace \"footer_content\" \"{footerContent}\"    - -",
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        // Start the process
        var process = new Process()
        {
            StartInfo = processStartInfo
        };
        process.Start();
        // Write the HTML content to the standard input of the process
        using (var streamWriter = new StreamWriter(process.StandardInput.BaseStream))
        {
            streamWriter.WriteLine(htmlContent);
            streamWriter.Close();
        }
        // Read the PDF output from the standard output of the process
        var pdfStream = new MemoryStream();
        using (var streamReader = new StreamReader(process.StandardOutput.BaseStream))
        {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = streamReader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                pdfStream.Write(buffer, 0, bytesRead);
            }
            streamReader.Close();
        }
        // Return the PDF file as the response
        return File(pdfStream.ToArray(), "application/pdf");
    }


  [HttpGet]
    [Route("print/html/{invoiceId}/{docType}/{templateId}")]
    public async Task<IActionResult> PrintHtmlAsync(string invoiceId, string docType, Guid templateId)
    {

        ViewModel = await _documentAppService.GetPrintDocumentAsync(Guid.Parse(invoiceId));
        ViewModel.DocumentType = documentTypes[docType];
        var templateModels = await _templateAppService.GetAsync(templateId);


        dynamic settingsObject = System.Text.Json.JsonSerializer.Deserialize<dynamic>(templateModels.CssCustomization);
        dynamic settings = JsonConvert.DeserializeObject<dynamic>(templateModels.CssCustomization);
        ViewModel.Settings = settingsObject;

        var fileDto = await _fileAppService.GetBlobAsync(new GetBlobRequestDto { Name = ViewModel.Company.Id.ToString() });
        if (ViewModel.Company.Id != Guid.Empty)
            ViewModel.Company.LogoBase = Convert.ToBase64String(fileDto.Content);


        var handlebars = Handlebars.Create();
        handlebars.Configuration.UseJson();

        string htmlTemplate = GetHtmlText($"{this._webHostEnvironment.WebRootPath}//templates//{docType}//standard.html");
        var template = handlebars.Compile(htmlTemplate);
        var htmlContent = template(ViewModel);


//Return the Html content
        return new ContentResult
        {
            Content = htmlContent,
            ContentType = "text/html",
            StatusCode = 200
        };

    }


}


convert and improve this to abp.io appservice class