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

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(OrderItemsReceipt receipt)
    {
        var commands = new List<PrintCommand>();

        // Header box
        AddHeaderBox(commands, receipt);

        // Client Notes
        if (!string.IsNullOrEmpty(receipt.ClientNotes))
        {
            commands.Add(new PrintCommand($"|Client Notes: {receipt.ClientNotes}"));
        }

        // Separator line
        commands.Add(new PrintCommand(new string('-', _lineWidth)));

        // Items
        foreach (var item in receipt.Items)
        {
            commands.Add(new PrintCommand(""));
            AddOrderItem(commands, item);
        }

        return commands;
    }

    private void AddHeaderBox(List<PrintCommand> commands, OrderItemsReceipt receipt)
    {
        // Column widths (fixed proportions)
        int col1Width = 8;  // Order column
        int col3Width = 12; // Date/Time column
        int col2Width = _lineWidth - col1Width - col3Width - 4; // QR column (4 for borders |)

        // Prepare column content with labels on first line, values on subsequent lines
        var col1Lines = new List<string> { "Order:" };
        col1Lines.AddRange(WrapText($"#{receipt.OrderNumber}", col1Width));

        var col2Lines = new List<string> { "QR:" };
        col2Lines.AddRange(WrapText(receipt.QRInfo, col2Width));

        var col3Lines = new List<string>
        {
            $"{receipt.DateTime:dd.MM.yyyy}",
            $"{receipt.DateTime:HH:mm:ss}"
        };

        // Determine max rows needed
        int maxRows = Math.Max(Math.Max(col1Lines.Count, col2Lines.Count), col3Lines.Count);

        // Pad columns to have equal rows
        while (col1Lines.Count < maxRows) col1Lines.Add("");
        while (col2Lines.Count < maxRows) col2Lines.Add("");
        while (col3Lines.Count < maxRows) col3Lines.Add("");

        // Top border
        commands.Add(new PrintCommand("+" + new string('-', col1Width) + "+" + new string('-', col2Width) + "+" + new string('-', col3Width) + "+"));

        // Content rows
        for (int i = 0; i < maxRows; i++)
        {
            string row = "|" +
                CenterInWidth(col1Lines[i], col1Width) + "|" +
                CenterInWidth(col2Lines[i], col2Width) + "|" +
                CenterInWidth(col3Lines[i], col3Width) + "|";

            commands.Add(new PrintCommand(row, isBold: i == 0));
        }

        // Bottom border
        commands.Add(new PrintCommand("+" + new string('-', col1Width) + "+" + new string('-', col2Width) + "+" + new string('-', col3Width) + "+"));
    }

    private List<string> WrapText(string text, int maxWidth)
    {
        var lines = new List<string>();

        if (string.IsNullOrEmpty(text))
        {
            lines.Add("");
            return lines;
        }

        // Trim to fit within column
        while (text.Length > 0)
        {
            if (text.Length <= maxWidth)
            {
                lines.Add(text);
                break;
            }

            // Find a good break point (prefer space)
            int breakPoint = text.LastIndexOf(' ', Math.Min(maxWidth, text.Length - 1));
            if (breakPoint <= 0 || breakPoint > maxWidth)
            {
                breakPoint = maxWidth;
            }

            lines.Add(text.Substring(0, breakPoint).TrimEnd());
            text = text.Substring(breakPoint).TrimStart();
        }

        return lines;
    }

    private void AddOrderItem(List<PrintCommand> commands, OrderItem item)
    {
        // Main item line: "1 Item Name          x1" or "3 Item Name    Size: L x2"
        string numberPart = $"{item.Number}";
        string namePart = item.Name;
        string quantityPart = $"x{item.Quantity}";

        string sizePart = "";
        if (!string.IsNullOrEmpty(item.Size))
        {
            sizePart = $"Size: {item.Size} ";
        }

        string rightPart = sizePart + quantityPart;
        int spacesNeeded = _lineWidth - numberPart.Length - 1 - namePart.Length - rightPart.Length;
        if (spacesNeeded < 1) spacesNeeded = 1;

        string mainLine = numberPart + " " + namePart + new string(' ', spacesNeeded) + rightPart;
        commands.Add(new PrintCommand(mainLine));

        // Sub-items
        foreach (var subItem in item.SubItems)
        {
            commands.Add(new PrintCommand($"  - {subItem}"));
        }

        // Modifications
        if (item.Modifications != null && (item.Modifications.Removed.Any() || item.Modifications.Added.Any()))
        {
            commands.Add(new PrintCommand("  Change of"));
            commands.Add(new PrintCommand("  Ingredients:"));

            foreach (var removed in item.Modifications.Removed)
            {
                commands.Add(new PrintCommand($"  - {removed}"));
            }

            foreach (var added in item.Modifications.Added)
            {
                commands.Add(new PrintCommand($"  + {added}"));
            }
        }

        // SpecialInstruction
        if (!string.IsNullOrEmpty(item.Comment))
        {
            commands.Add(new PrintCommand($"  SpecialInstruction: {item.Comment}"));
        }
    }

    private string CenterInWidth(string text, int width)
    {
        if (string.IsNullOrEmpty(text))
            return new string(' ', width);

        if (text.Length >= width)
            return text.Substring(0, width);

        int totalPadding = width - text.Length;
        int leftPadding = totalPadding / 2;
        int rightPadding = totalPadding - leftPadding;

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