#define CREATE_PREVIEW_HTML
using iText.Html2pdf;
using KarleyLibrary.Erweiterungen;
using PDFtoPrinter;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WK5.Core.Drucken.Briefe;
using WK5.Core.Email;
using WK5.Core.Models;

namespace WK5.Core.Drucken.Zeiterfassungen
{
    public class PrintZeiterfassung : PrintBase
    {
        private readonly IReadOnlyList<Zeiterfassung> _zeiten;
        private readonly BriefRegelsatz _regeln;
        private readonly Kunde _kunde;
        private readonly DateTime _von;
        private readonly DateTime _bis;
        private readonly IReadOnlyList<Personal> _mitarbeiter;

        private PrintZeiterfassung(IReadOnlyList<Zeiterfassung> zeiten, BriefRegelsatz regeln, Kunde kunde, DateTime von, DateTime bis, IReadOnlyList<Personal> mitarbeiter)
        {
            _layoutFile = "AuswertungZeiterfassung.html";
            _template = String.Empty;
            _zeiten = zeiten;
            _regeln = regeln;
            _kunde = kunde;
            _von = von;
            _bis = bis;
            _mitarbeiter = mitarbeiter;
        }
        public static async Task<PrintZeiterfassung> CreateAsync(IReadOnlyList<Zeiterfassung> zeiten, BriefRegelsatz regeln, string kundennummer, DateTime von, DateTime bis, IReadOnlyList<Personal> mitarbeiter, FbController2 fbController)
        {
            Kunde kunde = await Kunde.GetKundeAsync(kundennummer) ?? throw new NullReferenceException(nameof(kunde));
            var myClass = new PrintZeiterfassung(zeiten, regeln, kunde, von, bis, mitarbeiter);
            await myClass.InitializeAsync();
            return myClass;
        }
        public override string Print(string speicherpfad)
        {
            string filename = $"ZEITEN_{_kunde.KUND_A_NR}_{_von:yyyy_MM_dd}_{_bis:yyyy_MM_dd}.pdf";

#if CREATE_PREVIEW_HTML
            File.WriteAllText(Path.Combine(speicherpfad, $"ZEITEN_{_kunde.KUND_A_NR}_{_von:yyyy_MM_dd}_{_bis:yyyy_MM_dd}.html"), _template);
#endif
            byte[] byteArray = Encoding.UTF8.GetBytes(_template);
            MemoryStream stream = new MemoryStream(byteArray);
            ConverterProperties converterProperties = new ConverterProperties()
                .SetBaseUri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LAYOUT_PATH));

            string fullPath = Path.Combine(speicherpfad, filename);
            if (File.Exists(fullPath))
            {
                File.Delete(fullPath);
            }

            HtmlConverter.ConvertToPdf(stream, new FileStream(fullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None), converterProperties);

            return fullPath;
        }


        protected override string GenerateDisplayCss()
        {
            StringBuilder cssBuilder = new StringBuilder();
            cssBuilder.AppendLine("<style>");

            if (!_regeln.ShowFooter)
            {
                cssBuilder.AppendLine("\t#footer {");
                //cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t\tvisibility: hidden;");
                cssBuilder.AppendLine("\t\topacity: 0;");
                cssBuilder.AppendLine("\t\tcolor: rgba(0,0,0,0);");
                cssBuilder.AppendLine("\t\ttransform: scale(0);");
                cssBuilder.AppendLine("\t}");
            }

            if (!_regeln.ShowHeader)
            {
                cssBuilder.AppendLine("\t.karley-header {");
                //cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t\tvisibility: hidden;");
                cssBuilder.AppendLine("\t\topacity: 0;");
                cssBuilder.AppendLine("\t\tcolor: rgba(0,0,0,0);");
                cssBuilder.AppendLine("\t\ttransform: scale(0);");
                cssBuilder.AppendLine("\t}");
            }

            if (!_regeln.ShowAdresszeile2)
            {
                cssBuilder.AppendLine("\t.display-addresszeile2{");
                cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t}");
            }

            if (!_regeln.ShowAdresszeile3)
            {
                cssBuilder.AppendLine("\t.display-addresszeile3{");
                cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t}");
            }

            if (!_regeln.ShowAdresszeile4)
            {
                cssBuilder.AppendLine("\t.display-addresszeile4{");
                cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t}");
            }

            if (!_regeln.ShowAdresszeileLand)
            {
                cssBuilder.AppendLine("\t.display-empfaenger-land{");
                cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t}");
            }

            if (!_zeiten.Any(x => !x.WirdBerechnet || x.IstRemote || x.StartDatum.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday))
            {
                cssBuilder.AppendLine("\t.legende{");
                cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t}");
            }

            if (!_zeiten.Any(x => x.IstRemote))
            {
                cssBuilder.AppendLine("\t.remote-einheiten{");
                cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t}");
            }

            if (!GlobalConfig.Configuration.UseZeiteinheiten)
            {
                cssBuilder.AppendLine("\t.display-einheiten{");
                cssBuilder.AppendLine("\t\tdisplay: none;");
                cssBuilder.AppendLine("\t}");
            }

            cssBuilder.AppendLine("</style>");

            return cssBuilder.ToString();
        }

        protected override async Task InitializeAsync()
        {
            string layoutPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LAYOUT_PATH, _layoutFile);
            _template = await File.ReadAllTextAsync(layoutPath);
            SetRegeln();
            _template = await SetTemplateVariables();
        }

        protected override Task InitializeAsync(FbController2 fbController)
        {
            throw new NotImplementedException();
        }

        protected override void SetRegeln()
        {
            _regeln.ShowAdresszeileLand = _kunde.KUND_A_LAND != "DE";
            _regeln.ShowAdresszeile2 = !String.IsNullOrWhiteSpace(_kunde.KUND_A_NAME2);
            _regeln.ShowAdresszeile3 = !String.IsNullOrWhiteSpace(_kunde.KUND_A_NAME3);
            _regeln.ShowAdresszeile4 = false;
        }

        protected override async Task<string> SetTemplateVariables()
        {

            StringBuilder zeitenBuilder = new StringBuilder();
            decimal gesamtdauer = 0;
            decimal gesamtdauer_berechnet = 0;
            decimal gesamtdauer_remote = 0;
            decimal gesamtdauer_vor_ort = 0;
            decimal gesamt_kilometer = 0;
            int arbeitswerte_vorort = 0;
            int arbeitswerte_remote = 0;
            foreach (var zeit in _zeiten)
            {

                if (zeit.WirdBerechnet)
                {
                    if (zeit.IstRemote)
                    {
                        zeitenBuilder.AppendLine("<tr class=\"bg-info\">");
                    }
                    else if(zeit.StartDatum.DayOfWeek is DayOfWeek.Saturday)
                    {
                        zeitenBuilder.AppendLine("<tr class=\"bg-samstag\">");
                    }
                    else if(zeit.StartDatum.DayOfWeek is DayOfWeek.Sunday)
                    {
                        zeitenBuilder.AppendLine("<tr class=\"bg-sonntag\">");
                    }
                    else
                    {
                        zeitenBuilder.AppendLine("<tr>");
                    }
                }
                else
                {
                    zeitenBuilder.AppendLine("<tr class=\"bg-ohne-berechnung\">");
                }

                zeitenBuilder.AppendLine("\t<td>");
                zeitenBuilder.AppendLine($"\t\t{_mitarbeiter.FirstOrDefault(x => x.PERS_N_NR == zeit.AnlageUserId)?.GetName()}");
                zeitenBuilder.AppendLine("\t</td>");

                zeitenBuilder.AppendLine("\t<td>");
                zeitenBuilder.AppendLine($"\t\t{zeit.StartDatum.ToShortDateString()}, {zeit.StartZeit.ToShortTimeString()}");
                zeitenBuilder.AppendLine("\t</td>");

                zeitenBuilder.AppendLine("\t<td>");
                zeitenBuilder.AppendLine($"\t\t{zeit.EndeDatum.ToShortDateString()}, {zeit.EndeZeit.ToShortTimeString()}");
                zeitenBuilder.AppendLine("\t</td>");

                zeitenBuilder.AppendLine("\t<td>");
                zeitenBuilder.AppendLine($"\t\t{zeit.DauerInMinuten}");
                zeitenBuilder.AppendLine("\t</td>");

                zeitenBuilder.AppendLine("\t<td>");
                zeitenBuilder.AppendLine($"\t\t{ToZeiteinheiten(zeit.DauerInMinuten)}");
                zeitenBuilder.AppendLine("\t</td>");

                zeitenBuilder.AppendLine("</tr>");

                if (!string.IsNullOrEmpty(zeit.Notiz) || zeit.Belegnummer > 0)
                {
                    zeitenBuilder.AppendLine("<tr class=\"zeit-notiz\">");
                    zeitenBuilder.AppendLine("\t<td colspan=\"4\">");
                    if (zeit.Belegnummer > 0)
                    {
                        zeitenBuilder.AppendLine($"\t\t<span class=\"font-weight-bold d-block\">{zeit.Typ}-{zeit.Belegnummer}</span>");
                    }
                    if (!string.IsNullOrEmpty(zeit.Notiz))
                    {
                        zeitenBuilder.AppendLine($"\t\t{zeit.Notiz}");
                    }
                    zeitenBuilder.AppendLine("\t</td>");
                    zeitenBuilder.AppendLine("</tr>");
                }


                gesamtdauer += zeit.DauerInMinuten;
                gesamt_kilometer += zeit.Kilometer;
                if (zeit.WirdBerechnet)
                {
                    gesamtdauer_berechnet += zeit.DauerInMinuten;

                    if (zeit.IstRemote)
                    {
                        gesamtdauer_remote += zeit.DauerInMinuten;
                        arbeitswerte_remote += (int)ToZeiteinheiten(zeit.DauerInMinuten);
                    }
                    else
                    {
                        gesamtdauer_vor_ort += zeit.DauerInMinuten;
                        arbeitswerte_vorort += (int)ToZeiteinheiten(zeit.DauerInMinuten);
                    }
                }
            }

            // Zum debuggen
            //gesamtdauer += 10000;
            //gesamtdauer_berechnet += 12000;

            string gesamt = GlobalConfig.Configuration.UseDezimalzeit
                ? $"{ToStunden(gesamtdauer).ToString("0.00").Replace(",", ":")}, dez: {ToDecimalStunden(gesamtdauer):0.00} h"
                : $"{ToStunden(gesamtdauer).ToString("0.00").Replace(",", ":")} h";

            string gesamt_berechnet = GlobalConfig.Configuration.UseDezimalzeit
                ? $"{ToStunden(gesamtdauer_berechnet).ToString("0.00").Replace(",", ":")}, dez: {ToDecimalStunden(gesamtdauer_berechnet):0.00} h"
                : $"{ToStunden(gesamtdauer_berechnet).ToString("0.00").Replace(",", ":")} h";

            

            _template = _template
                .Replace("{{ DISPLAY_CSS }}", GenerateDisplayCss())
                .Replace("{{ IMPRESSUM }}", GlobalConfig.Configuration.FirmenDaten.ImpressumHtmlDruckformulare())
                .Replace("{{ ABS_FIRMA }}", GlobalConfig.Configuration.FirmenDaten.Firmenname)
                .Replace("{{ ABS_STRASSE }}", GlobalConfig.Configuration.FirmenDaten.Firmenanschrift.Strasse)
                .Replace("{{ ABS_LAND }}", GlobalConfig.Configuration.FirmenDaten.Firmenanschrift.Land)
                .Replace("{{ ABS_PLZ }}", GlobalConfig.Configuration.FirmenDaten.Firmenanschrift.Postleitzahl)
                .Replace("{{ ABS_ORT }}", GlobalConfig.Configuration.FirmenDaten.Firmenanschrift.Ort)
                .Replace("{{ ADDRESSZEILE1 }}", _kunde.KUND_A_NAME1)
                .Replace("{{ ADDRESSZEILE2 }}", _kunde.KUND_A_NAME2)
                .Replace("{{ ADDRESSZEILE3 }}", _kunde.KUND_A_NAME3)
                .Replace("{{ ADDRESSZEILE4 }}", string.Empty)
                .Replace("{{ EMP_STRASSE }}", _kunde.KUND_A_STRASSE)
                .Replace("{{ EMP_LAND }}", _kunde.KUND_A_LAND)
                .Replace("{{ EMP_PLZ }}", _kunde.KUND_A_PLZ)
                .Replace("{{ EMP_ORT }}", _kunde.KUND_A_ORT)
                .Replace("{{ DATUM }}", DateTime.Now.ToShortDateString())
                .Replace("{{ KUNDENNUMMER }}", _kunde.KUND_A_NR)
                .Replace("{{ ZEITEN }}", zeitenBuilder.ToString())
                .Replace("{{ ZEITEN_UEBERSCHRIFT }}", $"{_von.ToShortDateString()}-{_bis.ToShortDateString()}")
                .Replace("{{ STUNDEN }}", gesamt)
                .Replace("{{ ABZURECHNENDE_LEISTUNGEN }}", gesamt_berechnet)
                .Replace("{{ KILOMETER }}", gesamt_kilometer.ToString())
                .Replace("{{ ABZURECHNENDE_EINHEITEN_REMOTE }}", $"{arbeitswerte_remote}")
                .Replace("{{ ABZURECHNENDE_EINHEITEN_VOR_ORT }}", $"{arbeitswerte_vorort}")
                ;

            return await Task.FromResult(_template);
        }

        private static decimal ToStunden(decimal minuten)
        {
            decimal rest = minuten % 60 / 100;
            var tmp = Math.Floor(minuten / 60);
            return Math.Round(tmp + rest, 2);
        }

        private static decimal ToDecimalStunden(decimal minuten)
        {
            return Math.Round(minuten / 60, 2);
        }

        private static decimal ToZeiteinheiten(decimal minuten)
        {
            if (GlobalConfig.Configuration.ZeiteinheitInMinuten is 0)
            {
                return 0;
            }

            return Math.Ceiling(minuten / GlobalConfig.Configuration.ZeiteinheitInMinuten);
        }
    }
}
