// ===== Teuanjai Radio — XLSX writer (real .xlsx, no Excel warning) =====
// สร้างไฟล์ .xlsx จริง (ZIP ของ XML) รองรับหลายชีท เปิดด้วย Excel/Sheets ได้ไม่มี warning

function _u8(s) { return new TextEncoder().encode(s); }
const _CRC = (function () {
  const t = [];
  for (let n = 0; n < 256; n++) { let c = n; for (let k = 0; k < 8; k++) c = c & 1 ? 0xEDB88320 ^ (c >>> 1) : c >>> 1; t[n] = c >>> 0; }
  return t;
})();
function _crc32(u8) { let crc = 0xFFFFFFFF; for (let i = 0; i < u8.length; i++) crc = _CRC[(crc ^ u8[i]) & 0xFF] ^ (crc >>> 8); return (crc ^ 0xFFFFFFFF) >>> 0; }

// store-only ZIP -> Blob
function _zip(files) {
  const chunks = [], central = []; let offset = 0;
  const u16 = (n) => [n & 0xFF, (n >>> 8) & 0xFF];
  const u32 = (n) => [n & 0xFF, (n >>> 8) & 0xFF, (n >>> 16) & 0xFF, (n >>> 24) & 0xFF];
  files.forEach((f) => {
    const name = _u8(f.name), data = f.data, crc = _crc32(data);
    const local = [].concat(u32(0x04034b50), u16(20), u16(0x0800), u16(0), u16(0), u16(0), u32(crc), u32(data.length), u32(data.length), u16(name.length), u16(0));
    chunks.push(new Uint8Array(local), name, data);
    const cen = [].concat(u32(0x02014b50), u16(20), u16(20), u16(0x0800), u16(0), u16(0), u16(0), u32(crc), u32(data.length), u32(data.length), u16(name.length), u16(0), u16(0), u16(0), u16(0), u32(0), u32(offset));
    central.push(new Uint8Array(cen), name);
    offset += local.length + name.length + data.length;
  });
  let cenSize = 0; central.forEach((c) => cenSize += c.length);
  const end = [].concat(u32(0x06054b50), u16(0), u16(0), u16(files.length), u16(files.length), u32(cenSize), u32(offset), u16(0));
  return new Blob(chunks.concat(central, [new Uint8Array(end)]), { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
}

function _xesc(s) { return String(s == null ? "" : s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); }
function _colLetter(i) { let s = ""; i += 1; while (i > 0) { const m = (i - 1) % 26; s = String.fromCharCode(65 + m) + s; i = Math.floor((i - 1) / 26); } return s; }

function _sheetXml(sheet) {
  const allRows = [sheet.headers].concat(sheet.rows);
  let body = "";
  allRows.forEach((row, ri) => {
    let cells = "";
    row.forEach((val, ci) => {
      const ref = _colLetter(ci) + (ri + 1);
      if (typeof val === "number" && isFinite(val)) {
        cells += '<c r="' + ref + '"><v>' + val + "</v></c>";
      } else {
        cells += '<c r="' + ref + '" t="inlineStr"><is><t xml:space="preserve">' + _xesc(val) + "</t></is></c>";
      }
    });
    body += '<row r="' + (ri + 1) + '">' + cells + "</row>";
  });
  return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>' + body + "</sheetData></worksheet>";
}

// sheets: [{name, headers:[], rows:[[...]]}]
function buildXlsxBlob(sheets) {
  const types = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
    + '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'
    + '<Default Extension="xml" ContentType="application/xml"/>'
    + sheets.map((s, i) => '<Override PartName="/xl/worksheets/sheet' + (i + 1) + '.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>').join("")
    + '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/></Types>';
  const rels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
    + '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>';
  const wb = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets>'
    + sheets.map((s, i) => '<sheet name="' + _xesc(s.name).slice(0, 31) + '" sheetId="' + (i + 1) + '" r:id="rId' + (i + 1) + '"/>').join("")
    + "</sheets></workbook>";
  const wbRels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
    + sheets.map((s, i) => '<Relationship Id="rId' + (i + 1) + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet' + (i + 1) + '.xml"/>').join("")
    + "</Relationships>";

  const files = [
    { name: "[Content_Types].xml", data: _u8(types) },
    { name: "_rels/.rels", data: _u8(rels) },
    { name: "xl/workbook.xml", data: _u8(wb) },
    { name: "xl/_rels/workbook.xml.rels", data: _u8(wbRels) },
  ];
  sheets.forEach((s, i) => files.push({ name: "xl/worksheets/sheet" + (i + 1) + ".xml", data: _u8(_sheetXml(s)) }));
  return _zip(files);
}

function downloadBlob(filename, blob) {
  try {
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url; a.download = filename;
    document.body.appendChild(a); a.click();
    setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 250);
    return true;
  } catch (e) { return false; }
}

Object.assign(window, { buildXlsxBlob, downloadBlob });
