namespace Inspectron.Epson.PrintServer.Printers.Utils.FinalRecipe;

public class ReceiptConverter
{
    private readonly int _lineWidth;
    private readonly int _bigFontLineWidth;

    public ReceiptConverter(int lineWidth = 42, int bigFontLineWidth = 21)
    {
        _lineWidth = lineWidth;
        _bigFontLineWidth = bigFontLineWidth;
    }

    public List<PrintCommand> ConvertToPrintCommands(FinalReceipt finalReceipt)
    {
        var commands = new List<PrintCommand>();

        // Header - Company info
        commands.Add(new PrintCommand(Center(finalReceipt.CompanyName, false)));
        commands.Add(new PrintCommand(Center(finalReceipt.Address1, false)));
        commands.Add(new PrintCommand(Center(finalReceipt.Address2, false)));
        commands.Add(new PrintCommand(Center(finalReceipt.Phone, false)));
        commands.Add(new PrintCommand(""));
        commands.Add(new PrintCommand(""));
        if (finalReceipt.IsDebtor)
        {
            commands.Add(new PrintCommand("Debitorenrechnung"));
        }
        // FinalReceipt info
        string receiptLine = "";
        if (finalReceipt.ReceiptNumber != null)
            receiptLine += $"Rechnung Nr. {finalReceipt.ReceiptNumber}".PadRight(_lineWidth / 2);
        else
            receiptLine += $"".PadRight(_lineWidth / 2);
        receiptLine += $"{finalReceipt.DateTime:HH:mm dd.MM.yyyy}".PadLeft(_lineWidth / 2);
        commands.Add(new PrintCommand(receiptLine,isBold:true));
        commands.Add(new PrintCommand($"Guests: {finalReceipt.Guests}"));
        commands.Add(new PrintCommand(""));

        // Items
        foreach (var item in finalReceipt.Items)
        {
            PrintItem(item, commands);
        }

        commands.Add(new PrintCommand("")); // Reini
        commands.Add(new PrintCommand("---------".PadLeft(_lineWidth)));
        commands.Add(new PrintCommand("")); //Reini

        

        // Total
        string totalLine = $"Summe:  {finalReceipt.Total:F2} {finalReceipt.Currency}";
        commands.Add(new PrintCommand(Center(totalLine, true), true, true));
        commands.Add(new PrintCommand(""));

        // Alternate currency
        if (finalReceipt.TotalInAlternateCurrency.HasValue)
        {
            string altCurrencyLine = $"{finalReceipt.TotalInAlternateCurrency:F2} {finalReceipt.AlternateCurrency}";
            commands.Add(new PrintCommand(altCurrencyLine.PadLeft(_lineWidth)));
            commands.Add(new PrintCommand(""));
        }

        // Discount
        if (finalReceipt.DiscountInfo != null)
        {

            commands.Add(new PrintCommand(finalReceipt.DiscountInfo.Description.PadRight(_lineWidth / 2) + (finalReceipt.DiscountInfo.Amount.ToString("F2") + " " + finalReceipt.DiscountInfo.Currency).PadLeft(_lineWidth / 2)));
            commands.Add(new PrintCommand(""));
        }

        // Split payments
        if (finalReceipt.SplitPayments != null && finalReceipt.SplitPayments.Count > 0)
        {
            foreach (var splitPayment in finalReceipt.SplitPayments)
            {
                string splitLine = $"{splitPayment.PaymentMethod}: {splitPayment.Amount:F2} {splitPayment.Currency}";
                commands.Add(new PrintCommand(splitLine.PadLeft(_lineWidth)));
            }
            commands.Add(new PrintCommand(""));
        }

        // Payment method
        string paymentLine = $"{finalReceipt.PaymentMethod}";
        string paymentAmount = $"{finalReceipt.PaymentAmount:F2} {finalReceipt.Currency}";
        int paymentSpaces = _lineWidth - paymentLine.Length - paymentAmount.Length;
        if (paymentSpaces < 1) paymentSpaces = 1;
        commands.Add(new PrintCommand(paymentLine + new string(' ', paymentSpaces) + paymentAmount,isBold:true));
        commands.Add(new PrintCommand(""));

        // Tax breakdown
        foreach (var tax in finalReceipt.TaxBreakdown)
        {
            string taxLine = "MwSt  %".PadRight(_lineWidth/4)+"  Brutto".PadRight(_lineWidth / 4) + "  Netto".PadRight(_lineWidth / 4) + "MwSt".PadLeft(_lineWidth / 4);
            if (finalReceipt.TaxBreakdown.IndexOf(tax) == 0)
            {
                commands.Add(new PrintCommand(taxLine));
            }

            string taxDetail = ($"{tax.Category}:"+ $"{tax.Rate}%".PadLeft(5)).PadRight(_lineWidth / 4) + $"{tax.Gross:F2} {tax.Currency}".PadLeft(_lineWidth/4)+$"{tax.Net:F2} {tax.Currency}".PadLeft(_lineWidth/4)+$"{tax.TaxAmount:F2} {tax.Currency}".PadLeft(_lineWidth / 4);
            commands.Add(new PrintCommand(taxDetail));
        }

        if (finalReceipt.TaxBreakdown.Count(x => x.Category.ToLower()!="d")==0)
        {
            commands.Add(new PrintCommand("Nicht mehrwertsteuerpflichtig"));
        }

        commands.Add(new PrintCommand(""));

        // Footer info
        commands.Add(new PrintCommand($"Bedient von:".PadLeft(_lineWidth / 2) + $" {finalReceipt.WaiterName}"));
        
        if(!string.IsNullOrEmpty(finalReceipt.Terminal))
            commands.Add(new PrintCommand($"Terminal:".PadLeft(_lineWidth / 2) + $" {finalReceipt.Terminal}"));

        commands.Add(new PrintCommand($"Tisch:".PadLeft(_lineWidth / 2)+$" {finalReceipt.TableNumber}"));
        commands.Add(new PrintCommand(""));
        commands.Add(new PrintCommand(""));

        // VAT number
        commands.Add(new PrintCommand(Center(finalReceipt.VatNumber, false)));
        commands.Add(new PrintCommand(""));

        // Payment Terminal Receipts
        if (finalReceipt.TerminalReceipts != null && finalReceipt.TerminalReceipts.Count > 0)
        {
            foreach (var terminal in finalReceipt.TerminalReceipts)
            {
                commands.Add(new PrintCommand(Center(terminal.ReceiptType, false)));
                commands.Add(new PrintCommand(Center(terminal.BookingType, false)));
                commands.Add(new PrintCommand(Center(terminal.PaymentSystem, false)));
                commands.Add(new PrintCommand(terminal.TransactionNumber));
                commands.Add(new PrintCommand($"{terminal.TransactionDateTime:dd.MM.yyyy}".PadRight(_lineWidth/2) + $"{terminal.TransactionDateTime:HH:mm:ss}".PadLeft(_lineWidth/2)));

                commands.Add(new PrintCommand($"Trm-Id:".PadRight(_lineWidth/2) + $"{terminal.TerminalId}".PadLeft(_lineWidth/2)));
                commands.Add(new PrintCommand($"AID:".PadRight(_lineWidth/2) + $"{terminal.AID}".PadLeft(_lineWidth/2)));
                commands.Add(new PrintCommand($"Trx. Seq-Cnt:".PadRight(_lineWidth/2) + $"{terminal.TransactionSeqCount}".PadLeft(_lineWidth/2)));
                commands.Add(new PrintCommand($"Trx. Ref-No:".PadRight(_lineWidth/2) + $"{terminal.TransactionRefNo}".PadLeft(_lineWidth/2)));
                commands.Add(new PrintCommand($"Auth. Code:".PadRight(_lineWidth/2) + $"{terminal.AuthCode}".PadLeft(_lineWidth/2)));
                commands.Add(new PrintCommand($"Acq-Id:".PadRight(_lineWidth/2) + $"{terminal.AcquirerId}".PadLeft(_lineWidth/2)));

                commands.Add(new PrintCommand($"EFT {terminal.Currency}:".PadRight(_lineWidth/2) + $"{terminal.EftAmount:F2}".PadLeft(_lineWidth/2)));
                commands.Add(new PrintCommand($"Trinkgeld {terminal.Currency}:".PadRight(_lineWidth/2) + $"{terminal.TipAmount:F2}".PadLeft(_lineWidth/2)));
                commands.Add(new PrintCommand($"Total-EFT {terminal.Currency}:".PadRight(_lineWidth/2) + $"{terminal.TotalEftAmount:F2}".PadLeft(_lineWidth/2)));

                commands.Add(new PrintCommand(new string('-', _lineWidth)));
                commands.Add(new PrintCommand(""));
            }
        }

        // Thank you message
        commands.Add(new PrintCommand(Center(finalReceipt.ThankYouMessage, false)));
        commands.Add(new PrintCommand(Center(finalReceipt.GoodbyeMessageLine1, false)));
        commands.Add(new PrintCommand(Center(finalReceipt.GoodbyeMessageLine2, false)));
        if (finalReceipt.IsDebtor)
        {
            commands.Add(new PrintCommand(""));
            commands.Add(new PrintCommand(""));
            commands.Add(new PrintCommand(""));
            commands.Add(new PrintCommand("".PadRight(_lineWidth, '-')));
            commands.Add(new PrintCommand("Unterschrift"));


        }

        return commands;
    }

    private void PrintItem(FinalReceiptItem item, List<PrintCommand> commands)
    {
        string quantityPrefix = $"{item.Quantity}x ";
        string prices = $"{item.UnitPrice:F2}" + $"{item.TotalPrice:F2}".PadLeft(7) + $" {item.TaxCategory}";
        string fullLine = quantityPrefix + item.Description;

        int spacesNeeded = _lineWidth - fullLine.Length - prices.Length;

        if (spacesNeeded >= 1 || string.IsNullOrEmpty(item.Description))
        {
            if (spacesNeeded < 1) spacesNeeded = 1;
            commands.Add(new PrintCommand(fullLine + new string(' ', spacesNeeded) + prices));
        }
        else
        {
            int continuationAvailable = _lineWidth - quantityPrefix.Length;
            int firstLineAvailable = continuationAvailable - prices.Length - 1;

            if (continuationAvailable <= 0)
            {
                // Prefix alone exceeds line width, print without wrapping
                commands.Add(new PrintCommand(fullLine));
            }
            else
            {
                var words = item.Description.Split(' ');
                var lines = new List<string>();
                string currentLine = "";
                bool isFirstLine = true;

                foreach (var word in words)
                {
                    int available = (isFirstLine && firstLineAvailable > 0) ? firstLineAvailable : continuationAvailable;

                    if (currentLine.Length == 0)
                    {
                        currentLine = word;
                    }
                    else if (currentLine.Length + 1 + word.Length <= available)
                    {
                        currentLine += " " + word;
                    }
                    else
                    {
                        lines.Add(currentLine);
                        currentLine = word;
                        if (isFirstLine) isFirstLine = false;
                    }
                }

                if (currentLine.Length > 0)
                {
                    lines.Add(currentLine);
                }

                // First line with prefix and right-aligned prices
                string firstLineText = quantityPrefix + lines[0];
                int firstSpaces = _lineWidth - firstLineText.Length - prices.Length;
                if (firstSpaces >= 1)
                {
                    commands.Add(new PrintCommand(firstLineText + new string(' ', firstSpaces) + prices));
                }
                else
                {
                    commands.Add(new PrintCommand(firstLineText));
                    commands.Add(new PrintCommand(prices.PadLeft(_lineWidth)));
                }

                // Continuation lines indented to align with description
                string continuationIndent = new string(' ', quantityPrefix.Length);
                for (int i = 1; i < lines.Count; i++)
                {
                    commands.Add(new PrintCommand(continuationIndent + lines[i]));
                }
            }
        }

        // SubItems
        if (item.SubItems != null)
        {
            foreach (var subItem in item.SubItems)
            {
                commands.Add(new PrintCommand($"  - {subItem}"));
            }
        }
    }

    private string Center(string text, bool isBigFont)
    {
        int effectiveLineWidth = isBigFont ? _bigFontLineWidth : _lineWidth;

        if (string.IsNullOrEmpty(text) || text.Length >= effectiveLineWidth)
            return text;

        int totalPadding = effectiveLineWidth - text.Length;
        int leftPadding = totalPadding / 2;

        return new string(' ', leftPadding) + text;
    }
}