const { describe, it } = require("node:test");
const assert = require("node:assert");
const { getDefaultTemplate } = require("../lib/receipt-template");
const {
  renderReceiptText,
  buildReceiptPreviewModel,
  getSampleOrder,
  hasFbrSection,
  footerRowWithQr,
  rightLine,
} = require("../lib/receipt-renderer");
const { DEFAULT_TEMPLATES } = require("../lib/template-engine-v2/index");

describe("receipt renderer", () => {
  it("renders default template with sample order", () => {
    const text = renderReceiptText(getDefaultTemplate(), getSampleOrder());
    assert.match(text, /TEST-1001/);
    assert.match(text, /Chicken Broast/);
    assert.match(text, /TOTAL:/);
    assert.match(text, /Payment: Cash/);
  });

  it("omits FBR block when order has no FBR data", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    const order = getSampleOrder(false);
    assert.equal(hasFbrSection(template, order), false);
    const text = renderReceiptText(template, order);
    assert.doesNotMatch(text, /FBR Digital Invoice/);
  });

  it("shows FBR block only when order includes FBR payload", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    const order = getSampleOrder(true);
    assert.equal(hasFbrSection(template, order), true);
    const text = renderReceiptText(template, order);
    assert.match(text, /FBR Digital Invoice/);
    assert.match(text, /\[FBR QR\]/);
  });

  it("right-aligns subtotal and total", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    const order = getSampleOrder(false);
    const text = renderReceiptText(template, order);
    const width = 32;
    assert.ok(text.includes(rightLine("Subtotal: Rs 1050.00", width)));
    assert.ok(text.includes(rightLine("TOTAL: Rs 1050.00", width)));
  });

  it("places business QR on footer row when link enabled", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    template.branding = {
      qrCode: { enabled: true, links: [{ url: "https://siraya.food" }] },
    };
    template.conditionals = { ...template.conditionals, showQrCode: true };
    template.footer = { lines: ["Thank you!"], align: "center" };
    const text = renderReceiptText(template, getSampleOrder(false));
    assert.match(text, /\[QR ROW\]/);
  });

  it("uses custom header lines from designer", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    template.header = {
      title: "My Cafe",
      lines: ["03001234567", "https://cafe.example.com", "Best broast in town"],
    };
    const text = renderReceiptText(template, getSampleOrder(false));
    assert.match(text, /My Cafe/);
    assert.match(text, /03001234567/);
    assert.match(text, /cafe\.example\.com/);
    assert.match(text, /Best broast in town/);
  });

  it("limits business QR links when FBR is present", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    template.branding = {
      qrCode: {
        enabled: true,
        links: [
          { url: "https://a.example" },
          { url: "https://b.example" },
          { url: "https://c.example" },
        ],
      },
    };
    template.conditionals.showQrCode = true;
    const links = require("../lib/receipt-renderer").resolveBusinessQrLinks(
      template,
      getSampleOrder(true),
      {},
      { hasFbr: true },
    );
    assert.equal(links.length, 2);
  });

  it("prints powered-by footer", () => {
    const text = renderReceiptText(getDefaultTemplate(), getSampleOrder(false));
    assert.match(text, /Powered by Siraya RMS/);
    assert.match(text, /Kiazend Technologies/);
    assert.match(text, /pos\.siraya\.food/);
    assert.doesNotMatch(text, /\u2122/);
  });

  it("hides loyalty section when disabled", () => {
    const template = getDefaultTemplate();
    template.sections.loyalty = false;
    const order = { ...getSampleOrder(), loyaltyDiscount: 100 };
    const text = renderReceiptText(template, order);
    assert.doesNotMatch(text, /Loyalty:/);
  });

  it("shows kitchen banner for kitchen_ticket", () => {
    const text = renderReceiptText(getDefaultTemplate(), getSampleOrder(), {
      receiptKind: "kitchen_ticket",
    });
    assert.match(text, /KITCHEN COPY/);
  });

  it("builds structured preview model with right-aligned total", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    const model = buildReceiptPreviewModel(template, getSampleOrder(false));
    const totalLine = model.bodyLines.find((l) => l.style === "total");
    assert.ok(totalLine);
    assert.equal(totalLine.align, "right");
    assert.match(totalLine.text, /TOTAL:/);
  });

  it("does not print header defaults when template header is empty", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    template.header = { title: "", lines: [] };
    const text = renderReceiptText(template, getSampleOrder(false), {
      businessConfig: {
        BUSINESS_NAME: "SIRAYA",
        BUSINESS_PHONE: "03254410555",
        BUSINESS_WEBSITE: "pos.siraya.food",
      },
    });
    const headerPart = text.split("TEST-1001")[0];
    assert.doesNotMatch(headerPart, /SIRAYA/);
    assert.doesNotMatch(headerPart, /03254410555/);
    assert.doesNotMatch(headerPart, /pos\.siraya\.food/);
  });

  it("prints full-width dividers on 80mm paper", () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    template.paperWidth = 42;
    const text = renderReceiptText(template, getSampleOrder(false));
    const dashLine = "-".repeat(48);
    assert.ok(text.includes(dashLine), "expected 48-char divider");
  });

  it("escpos output avoids GS ! size commands that stretch text", async () => {
    const template = JSON.parse(JSON.stringify(DEFAULT_TEMPLATES[0]));
    const order = {
      orderNumber: "T-1",
      orderType: "dine-in",
      items: [{ name: "Broast", quantity: 1, price: 450, total: 450 }],
      subtotal: 450,
      tax: 45,
      total: 495,
      paymentMethod: "Cash",
    };
    const bin = await require("../lib/receipt-renderer").renderReceipt(
      template,
      order,
    );
    assert.doesNotMatch(bin, /\x1D!\x01/);
    assert.doesNotMatch(bin, /\x1D!\x10/);
    assert.doesNotMatch(bin, /\x1D!\x30/);
    assert.match(bin, /Tax: Rs 45\.00/);
  });
});
