/* global React, Icon, Field, formatBaht, formatDateTH */
// ─────────────────────────────────────────────────────────────
//  Epson ePOS Print Module — TM-T82 / TM-T82III / TM-T82X
//  โปรโตคอล: ePOS-Print XML over WebSocket
// ─────────────────────────────────────────────────────────────

// ── XML helpers ──────────────────────────────────────────────
function _ex(s) {
  return String(s ?? "")
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
}

// จัดคอลัมน์ label (ซ้าย) + value (ขวา) ให้ครบ width ตัวอักษร
// * ภาษาไทย 1 ตัว ≈ 2 ช่อง (double-byte) — ใช้ hori_motion จัดแทนแพด
function _row(label, value, w) {
  const l = String(label);
  const v = String(value);
  const spaces = Math.max(1, w - l.length - v.length);
  return _ex(l + " ".repeat(spaces) + v);
}

const LINE_W = 32; // cols ที่ font_a 80mm (ปรับได้ตาม DIP switch)
const SEP    = "================================"; // 32 chars

// ── XML envelope ─────────────────────────────────────────────
function _wrap(body, devId = "local_printer") {
  return `<?xml version="1.0" encoding="utf-8"?>\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">\
<s:Body>\
<epos-print xmlns="http://www.epson-pos.com/schemas/2011/03/epos-print">\
${body}\
</epos-print>\
</s:Body>\
</s:Envelope>`;
}

// ── สร้าง ePOS XML จากข้อมูลใบเสร็จ ─────────────────────────
function buildReceiptXML(data, headerLines, footerLines) {
  const isRoom   = !!(data.no && data.customer);
  const isExtend = !!data.extendReceipt;
  const isDaily  = !!(data.plate);  // parking daily

  const since       = data.customer?.since;
  const checkoutPlan = data.customer?.checkoutPlan;
  const nights = isExtend
    ? (data.extendNights || 1)
    : (isRoom && since && checkoutPlan)
      ? Math.max(1, Math.round((new Date(checkoutPlan) - new Date(since)) / 86400000))
      : 1;
  const deposit    = (isRoom && !isExtend) ? (data.customer?.deposit || 0) : 0;
  const baseAmount = isDaily
    ? (data.amount || 0)
    : isRoom
      ? (isExtend ? (data.extendAmount || 0) : (data.rent || 0) * nights)
      : (data.monthly || 0);
  const total = baseAmount + deposit;

  // วันที่/เวลา (local)
  const now = new Date();
  const txDate = [
    now.getFullYear(),
    String(now.getMonth() + 1).padStart(2, "0"),
    String(now.getDate()).padStart(2, "0"),
  ].join("-");
  const txTime = `${String(now.getHours()).padStart(2,"0")}:${String(now.getMinutes()).padStart(2,"0")} น.`;

  let c = "";

  // ── Header ──
  c += `<text align="center"/><text font="font_b" size="2, 2"/>`;
  c += `<text>${_ex(headerLines[0] || "ParkingHome")}\n</text>`;
  c += `<text font="font_b" size="1, 1"/>`;
  for (let i = 1; i < headerLines.length; i++) {
    c += `<text>${_ex(headerLines[i])}\n</text>`;
  }
  c += `<text>${SEP}\n</text>`;

  // ── เลขที่ + วันที่ ──
  c += `<text align="left"/><text font="font_a"/>`;
  c += `<text>เลขที่: RC-${txDate.replace(/-/g,"")}-${_ex(data.no || data.spot || "X")}\n</text>`;
  c += `<text>วันที่ทำรายการ: ${_ex(formatDateTH(txDate))} ${txTime}\n</text>`;
  c += `<text>${SEP}\n</text>`;

  // ── รายละเอียด ──
  if (isDaily) {
    c += `<text>ทะเบียนรถ: ${_ex(data.plate)}\n</text>`;
    c += `<text>ช่องจอด  : ${_ex(data.spot)}\n</text>`;
    c += `<text>ระยะเวลา : ${_ex(data.hours)} ชม.\n</text>`;
  } else if (isRoom) {
    c += `<text>ห้อง : ${_ex(data.no)}  (${data.type === "daily" ? "รายวัน" : "รายเดือน"})\n</text>`;
    c += `<text>ผู้เช่า: ${_ex(data.customer.name)}\n</text>`;
    if (data.customer.phone)
      c += `<text>โทร  : ${_ex(data.customer.phone)}\n</text>`;
    if (isExtend) {
      if (data.extendFrom)
        c += `<text>ต่อพักจาก: ${_ex(formatDateTH(data.extendFrom))} 12.00\n</text>`;
      if (checkoutPlan)
        c += `<text>ถึงวันที่ : ${_ex(formatDateTH(checkoutPlan))} 12.00\n</text>`;
    } else {
      if (since)
        c += `<text>เข้าพัก  : ${_ex(formatDateTH(since))}\n</text>`;
      if (checkoutPlan)
        c += `<text>กำหนดออก : ${_ex(formatDateTH(checkoutPlan))} 12.00\n</text>`;
    }
  } else {
    // parking monthly
    c += `<text>ช่องจอด: ${_ex(data.no)}\n</text>`;
    c += `<text>ผู้เช่า : ${_ex(data.customer?.name || "—")}\n</text>`;
    if (data.customer?.phone)
      c += `<text>โทร    : ${_ex(data.customer.phone)}\n</text>`;
  }
  c += `<text>${SEP}\n</text>`;

  // ── รายการ ──
  if (isDaily) {
    c += `<text font="font_b"/><text>${_row("ค่าจอดรถ", formatBaht(baseAmount), LINE_W)}\n</text>`;
  } else if (isRoom) {
    if (isExtend) {
      c += `<text>ค่าห้องพัก x${nights} คืน\n</text>`;
      c += `<text font="font_b"/><text>${_row("", formatBaht(baseAmount), LINE_W)}\n</text>`;
    } else {
      c += `<text>ค่าห้องพัก x${nights} คืน\n</text>`;
      c += `<text>${_row("", formatBaht(baseAmount), LINE_W)}\n</text>`;
      if (deposit > 0) {
        c += `<text font="font_a"/><text>${_row("ค่าประกัน/มัดจำ", formatBaht(deposit), LINE_W)}\n</text>`;
      }
    }
  } else {
    c += `<text>ค่าจอดรถรายเดือน\n</text>`;
    c += `<text>${_row("", formatBaht(baseAmount), LINE_W)}\n</text>`;
  }

  c += `<text>${SEP}\n</text>`;
  c += `<text font="font_b" size="1, 2"/>`;
  c += `<text>${_row("รวมทั้งสิ้น", formatBaht(total), LINE_W)}\n</text>`;
  c += `<text font="font_a" size="1, 1"/>`;
  c += `<text>ชำระด้วย: ${_ex(data.method || "เงินสด")}\n</text>`;
  c += `<text>${SEP}\n</text>`;

  // ── Footer ──
  c += `<text align="center"/>`;
  for (const line of footerLines) {
    c += `<text>${_ex(line)}\n</text>`;
  }
  c += `<text>\n\n</text>`;
  c += `<cut type="feed"/>`;

  return _wrap(c);
}

// ── WebSocket send ────────────────────────────────────────────
async function epsonSend(ip, port, xml) {
  return new Promise((resolve, reject) => {
    // HTTPS page → ต้องใช้ WSS (port 8043 สำหรับ Epson SSL)
    // HTTP page  → WS (port 8008)
    const proto = location.protocol === "https:" ? "wss" : "ws";
    const wsUrl = `${proto}://${ip}:${port}`;

    let ws;
    try { ws = new WebSocket(wsUrl); }
    catch (e) { return reject(new Error("ไม่สามารถสร้าง WebSocket: " + e.message)); }

    const timer = setTimeout(() => {
      ws.close();
      reject(new Error("timeout"));
    }, 8000);

    ws.onopen  = () => ws.send(xml);
    ws.onmessage = (e) => { clearTimeout(timer); ws.close(); resolve(e.data); };
    ws.onerror = () => { clearTimeout(timer); reject(new Error("connection_error")); };
    ws.onclose = (e) => { if (!e.wasClean) { clearTimeout(timer); reject(new Error("closed")); } };
  });
}

// ── ทดสอบการเชื่อมต่อ ─────────────────────────────────────────
async function epsonTestPrint(ip, port) {
  const xml = _wrap(
    `<text align="center"/><text font="font_b" size="2, 2"/>` +
    `<text>ParkingHome\n</text>` +
    `<text font="font_a" size="1, 1"/>` +
    `<text>================================\n</text>` +
    `<text align="left"/>` +
    `<text>ทดสอบเครื่องพิมพ์สำเร็จ\n</text>` +
    `<text>IP: ${_ex(ip)}  Port: ${_ex(String(port))}\n</text>` +
    `<text>================================\n</text>` +
    `<text align="center"/>` +
    `<text>Epson TM-T82  ePOS Ready\n\n</text>` +
    `<cut type="feed"/>`
  );
  return epsonSend(ip, port, xml);
}

window.epsonSend     = epsonSend;
window.epsonTestPrint = epsonTestPrint;
window.buildReceiptXML = buildReceiptXML;
