using Meezi.API.Models.Orders;
using Meezi.API.Services.Printing;
using Meezi.Core.Enums;
using Xunit;

namespace Meezi.API.Tests;

public class PrintingTests
{
    private static OrderDto SampleOrder() => new(
        "order-abc12345",
        "cafe-1",
        "branch-1",
        "table-1",
        "5",
        "Ali",
        null,
        null,
        null,
        null,
        null,
        OrderType.DineIn,
        OrderSource.Pos,
        OrderStatus.Pending,
        200_000m,
        18_000m,
        0m,
        218_000m,
        0m,
        DateTime.UtcNow,
        [
            new OrderItemDto("i1", "m1", "Espresso", 2, 100_000m, null),
            new OrderItemDto("i2", "m2", "Void Latte", 1, 50_000m, null, true)
        ],
        [new PaymentDto("p1", PaymentMethod.Cash, 218_000m, PaymentStatus.Completed, null)]);

    private static ReceiptPrintContext Ctx(int paper = 80) => new(
        SampleOrder(),
        "کافه دمو",
        "شعبه اصلی",
        "خوش آمدید",
        "با تشکر",
        "wifi1234",
        paper,
        true);

    [Fact]
    public void ReceiptBuilder_ExcludesVoidedItems()
    {
        var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
        var text = System.Text.Encoding.UTF8.GetString(bytes);
        Assert.Contains("Espresso", text);
        Assert.DoesNotContain("Void Latte", text);
    }

    [Fact]
    public void ReceiptBuilder_AppliesPersianCalendarDate()
    {
        var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
        var text = System.Text.Encoding.UTF8.GetString(bytes);
        Assert.Contains("تاریخ:", text);
    }

    [Fact]
    public void ReceiptBuilder_ShowsTaxLine_WhenTaxNonZero()
    {
        var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
        var text = System.Text.Encoding.UTF8.GetString(bytes);
        Assert.Contains("مالیات", text);
    }

    [Fact]
    public void ReceiptBuilder_80mm_Uses48CharWidth()
    {
        var sep = new EscPosBuilder().Separator(48).Build();
        var receipt = new ReceiptBuilder().BuildReceipt(Ctx(80));
        Assert.NotEmpty(receipt);
        Assert.Contains(sep, receipt);
    }

    [Fact]
    public void ReceiptBuilder_58mm_Uses32CharWidth()
    {
        var sep = new EscPosBuilder().Separator(32).Build();
        var receipt = new ReceiptBuilder().BuildReceipt(Ctx(58));
        Assert.Contains(sep, receipt);
    }

    [Fact]
    public void KitchenTicket_IncludesItemNotes()
    {
        var order = SampleOrder() with
        {
            Items =
            [
                new OrderItemDto("i1", "m1", "Burger", 1, 100_000m, "بدون پیاز")
            ]
        };
        var ctx = Ctx() with { Order = order };
        var text = System.Text.Encoding.UTF8.GetString(new ReceiptBuilder().BuildKitchenTicket(ctx));
        Assert.Contains("بدون پیاز", text);
        Assert.Contains("آشپزخانه", text);
    }

    [Fact]
    public void EscPosBuilder_Cut_AppendsCorrectBytes()
    {
        var bytes = new EscPosBuilder().Cut().Build();
        Assert.Equal([0x1D, 0x56, 0x42, 0x03], bytes);
    }

    [Fact]
    public void EscPosBuilder_TwoColumns_PadsCorrectly()
    {
        var bytes = new EscPosBuilder().TwoColumns("کالا", "1000", 10).Build();
        var line = System.Text.Encoding.UTF8.GetString(bytes).TrimEnd('\n');
        Assert.Equal(10, line.Length);
        Assert.EndsWith("1000", line);
    }
}
