<?php
$is_edit = isset($trx) && $trx;
$action  = $is_edit ? site_url('receipt/update/'.$trx->id) : site_url('receipt/store');
$default_date = $is_edit && !empty($trx->trx_date)
    ? date('Y-m-d\TH:i', strtotime($trx->trx_date))
    : date('Y-m-d\TH:i');
$existing_cf = $is_edit ? ($trx->custom_fields ?? []) : [];

if (empty($stores)) { ?>
  <div class="alert alert-warning">&#x26A0;&#xFE0F; Belum ada <strong>Toko</strong>.
    <a href="<?= site_url('store/create') ?>">Tambah Toko</a> dulu.</div>
<?php return; }
if (empty($templates)) { ?>
  <div class="alert alert-warning">&#x26A0;&#xFE0F; Belum ada <strong>Template</strong>.
    <a href="<?= site_url('template/builder') ?>">Buat Template</a> dulu.</div>
<?php return; }
?>

<style>
.trx-layout { display:flex; gap:20px; align-items:flex-start; flex-wrap:wrap; }
.trx-form   { flex:1 1 400px; min-width:300px; }
.trx-preview-col { flex:0 0 270px; position:sticky; top:calc(var(--nav-h,52px)+12px); }

.receipt-box { background:#fff; border:1px solid #ddd; border-radius:10px; padding:12px; box-shadow:0 2px 10px rgba(0,0,0,.08); }
.receipt-box-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; font-size:12px; color:#666; font-weight:600; padding-bottom:8px; border-bottom:1px solid #f0f0f0; }
.receipt-paper { margin:0 auto; font-family:'Courier New',monospace; font-size:10.5px; line-height:1.55; background:#FFFEF8; border:1px dashed #e0d9c0; border-radius:4px; padding:10px 8px 20px; min-height:180px; overflow:hidden; transition:width .2s ease; }
.receipt-paper.paper-58 { width:210px; }
.receipt-paper.paper-80 { width:240px; }
.receipt-paper .r-bold{font-weight:bold} .receipt-paper .r-center{text-align:center;display:block} .receipt-paper .r-right{text-align:right;display:block} .receipt-paper .r-left{text-align:left;display:block} .receipt-paper .r-line{color:#bbb;display:block;letter-spacing:-1px} .receipt-paper .r-size2{font-size:12.5px} .receipt-paper .r-size3{font-size:14px}
.receipt-loading{display:none;text-align:center;color:#aaa;font-size:12px;padding:16px}
.dynamic-section { border:1px solid #E8F5E9; border-radius:8px; padding:14px; background:#F9FBF9; margin-bottom:14px; }
.dynamic-section-title { font-size:12px; font-weight:700; color:#2E7D32; margin-bottom:12px; display:flex; align-items:center; gap:6px; }
.dyn-row2 { display:flex; gap:10px; flex-wrap:wrap; }
.dyn-row2 .form-group { flex:1; min-width:100px; }
.multiply-result { background:#F3E5F5; border:1px solid #CE93D8; border-radius:7px; padding:10px 12px; display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
.multiply-result .mr-label { font-size:13px; font-weight:600; color:#6A1B9A; }
.multiply-result .mr-value { font-size:15px; font-weight:700; color:#4A148C; }
.date-row { display:flex; gap:8px; align-items:flex-end; flex-wrap:wrap; }
.date-row .form-group { flex:1; min-width:150px; margin-bottom:0; }
.date-format-badge { display:inline-block; background:#E3F2FD; color:#1565C0; font-size:11px; padding:3px 8px; border-radius:4px; font-family:monospace; margin-top:4px; }
.item-row{display:flex;gap:6px;align-items:center;margin-bottom:6px;flex-wrap:wrap}
.col-name{flex:3;min-width:100px} .col-qty{flex:1;min-width:55px} .col-price{flex:2;min-width:90px} .col-sub{flex:2;min-width:80px;color:#555;font-size:12px;padding:8px 4px;font-weight:600} .col-del{flex:0 0 auto}
</style>

<div class="trx-layout">

  <!-- FORM -->
  <div class="trx-form">
    <div class="card">
      <form action="<?= $action ?>" method="POST" id="trxForm">

        <!-- Toko & Template - selalu tampil -->
        <div class="form-row">
          <div class="form-group">
            <label>Toko *</label>
            <select name="store_id" id="inp_store" class="form-control" required onchange="schedulePreview()">
              <?php foreach ($stores as $s): ?>
                <option value="<?= $s->id ?>" <?= ($is_edit && $trx->store_id==$s->id)?'selected':'' ?>><?= htmlspecialchars($s->name) ?></option>
              <?php endforeach; ?>
            </select>
          </div>
          <div class="form-group">
            <label>Template *</label>
            <select name="template_id" id="inp_template" class="form-control" required onchange="onTemplateChange(this.value)">
              <?php foreach ($templates as $t): ?>
                <option value="<?= $t->id ?>"
                  <?= ($is_edit && $trx->template_id==$t->id) ? 'selected' : ($t->is_default && !$is_edit ? 'selected':'') ?>>
                  <?= htmlspecialchars($t->name) ?><?= $t->is_default?' (Default)':'' ?>
                </option>
              <?php endforeach; ?>
            </select>
          </div>
        </div>

        <!-- SYSTEM FIELDS - tampil hanya jika ada di template -->

        <!-- No. Invoice + Kasir (ditampilkan sesuai template) -->
        <div id="sf_invoice_row" class="form-row" style="display:none;">
          <div class="form-group" id="sf_invoice_field" style="display:none;">
            <label>No. Invoice</label>
            <input type="text" name="invoice_no" id="inp_invoice" class="form-control"
              value="<?= htmlspecialchars($trx->invoice_no??'') ?>" placeholder="Otomatis jika kosong"
              oninput="schedulePreview()">
          </div>
          <div class="form-group" id="sf_cashier_field" style="display:none;">
            <label>Kasir</label>
            <input type="text" name="cashier" id="inp_cashier" class="form-control"
              value="<?= htmlspecialchars($trx->cashier??'Admin') ?>" oninput="schedulePreview()">
          </div>
        </div>

        <!-- Tanggal Transaksi (ditampilkan sesuai template) -->
        <div id="sf_date_row" class="form-group" style="display:none;">
          <label>Tanggal Transaksi</label>
          <div class="date-row">
            <div class="form-group">
              <input type="datetime-local" name="trx_date" id="inp_trx_date" class="form-control"
                value="<?= $default_date ?>" onchange="schedulePreview()">
            </div>
            <button type="button" class="btn btn-light btn-sm" onclick="setDateNow()" style="margin-bottom:1px;">&#x23F1; Sekarang</button>
          </div>
          <div id="date_format_info"></div>
        </div>

        <!-- Catatan (ditampilkan sesuai template) -->
        <div id="sf_note_row" class="form-group" style="display:none;">
          <label>Catatan</label>
          <input type="text" name="note" id="inp_note" class="form-control"
            value="<?= htmlspecialchars($trx->note??'') ?>" placeholder="Opsional" oninput="schedulePreview()">
        </div>

        <!-- DYNAMIC SECTION (template flexible) -->
        <div id="dynamicSection" style="display:none;">
          <div class="dynamic-section">
            <div class="dynamic-section-title">&#x1F4E5; Isi Data Struk</div>
            <div id="dynamicFields"></div>
          </div>
        </div>

        <!-- CLASSIC SECTION -->
        <div id="classicSection" style="display:none;">
          <div class="form-group">
            <label>Daftar Item *</label>
            <div class="item-row" style="font-weight:600;font-size:12px;color:#666;margin-bottom:2px;">
              <div class="col-name">Nama Item</div><div class="col-qty">Qty</div>
              <div class="col-price">Harga</div><div class="col-sub">Subtotal</div><div class="col-del"></div>
            </div>
            <div id="itemList"></div>
            <button type="button" class="btn btn-light btn-sm" onclick="addItem()" style="margin-top:4px;">+ Tambah Item</button>
          </div>
        </div>

        <!-- SUMMARY (classic) -->
        <div id="summarySection" class="card" style="background:#F8F9FA;padding:12px 16px;display:none;">
          <div style="display:flex;justify-content:space-between;margin-bottom:6px;">
            <span>Subtotal</span><span id="disp_subtotal">Rp 0</span>
          </div>
          <div style="display:flex;justify-content:space-between;margin-bottom:6px;align-items:center;">
            <span>Diskon</span>
            <div style="display:flex;align-items:center;gap:6px;">
              <span>Rp</span>
              <input type="number" name="discount" id="inp_discount" class="form-control"
                style="width:110px;text-align:right;"
                value="<?= $is_edit?$trx->discount:0 ?>" min="0" oninput="recalcClassic();schedulePreview()">
            </div>
          </div>
          <div style="display:flex;justify-content:space-between;margin-bottom:6px;align-items:center;">
            <span>Pajak</span>
            <div style="display:flex;align-items:center;gap:6px;">
              <span>Rp</span>
              <input type="number" name="tax" id="inp_tax" class="form-control"
                style="width:110px;text-align:right;"
                value="<?= $is_edit?$trx->tax:0 ?>" min="0" oninput="recalcClassic();schedulePreview()">
            </div>
          </div>
          <hr style="margin:8px 0;">
          <div style="display:flex;justify-content:space-between;">
            <strong>TOTAL</strong>
            <strong id="disp_total" style="color:var(--primary);font-size:16px;">Rp 0</strong>
          </div>
        </div>

        <!-- MULTIPLY RESULTS (flexible) -->
        <div id="multiplyResults" style="margin-top:8px;"></div>

        <!-- Hidden fields -->
        <input type="hidden" name="items"         id="hItems"     value="[]">
        <input type="hidden" name="custom_fields" id="hCF"        value="{}">
        <input type="hidden" name="subtotal"      id="hSubtotal"  value="0">
        <input type="hidden" name="grand_total"   id="hGrandTotal" value="0">

        <div class="form-actions" style="margin-top:16px;">
          <button type="button" class="btn btn-primary" onclick="submitForm()">
            <?= $is_edit?'&#x1F4BE; Simpan &amp; Cetak':'&#x1F9FE; Buat &amp; Cetak' ?>
          </button>
          <a href="<?= site_url('receipt') ?>" class="btn btn-light">Batal</a>
        </div>

      </form>
    </div>
  </div>

  <!-- LIVE PREVIEW -->
  <div class="trx-preview-col">
    <div class="receipt-box">
      <div class="receipt-box-header">
        <span>&#x1F9FE; Preview Struk</span>
        <span id="previewStatus" style="color:#4CAF50;font-size:11px;">&#x25CF; Live</span>
      </div>
      <div id="previewLoading" class="receipt-loading">&#x23F3; Memuat...</div>
      <div id="receiptPaper" class="receipt-paper paper-58">Pilih template...</div>
      <div id="paperInfo" style="font-size:10px;color:#bbb;text-align:center;margin-top:6px;">58mm &#xB7; 32 karakter/baris</div>
    </div>
  </div>

</div>

<script>
const APP_URL     = '<?= site_url() ?>';
const IS_EDIT     = <?= $is_edit?'true':'false' ?>;
const EXISTING_CF = <?= json_encode($existing_cf) ?>;

let COLS            = 32;
let activePaperMm   = 58;
let previewTimer    = null;
let activeTplEls    = [];
let activeTplType   = 'classic';
let classicItems    = <?= json_encode($is_edit&&!empty($trx->items)?$trx->items:[['name'=>'','qty'=>1,'price'=>0]]) ?>;
let customFieldVals = Object.assign({}, EXISTING_CF);
let multiplyDefs    = [];

/* Tampilkan/sembunyikan system fields sesuai template */
function applySystemFields(elements, templateType) {
  if (templateType === 'flexible') {
    document.getElementById('sf_invoice_row').style.display   = 'none';
    document.getElementById('sf_invoice_field').style.display = 'none';
    document.getElementById('sf_cashier_field').style.display = 'none';
    document.getElementById('sf_date_row').style.display      = 'none';
    document.getElementById('sf_note_row').style.display      = 'none';
    return;
  }
  // Classic: cek placeholder {{...}} dalam elemen teks template
  const textBlob = elements
    .filter(e => e.element_type === 'text')
    .map(e => e.value || '')
    .join(' ');
  const has = key => textBlob.includes('{{' + key + '}}');

  const showInvoice = has('invoice_no');
  const showCashier = has('cashier');
  const showRow     = showInvoice || showCashier;

  document.getElementById('sf_invoice_row').style.display   = showRow    ? '' : 'none';
  document.getElementById('sf_invoice_field').style.display = showInvoice ? '' : 'none';
  document.getElementById('sf_cashier_field').style.display = showCashier ? '' : 'none';
  document.getElementById('sf_date_row').style.display      = has('date') ? '' : 'none';
  document.getElementById('sf_note_row').style.display      = has('note') ? '' : 'none';
}

/* Update paper size di preview */
function applyPaperSize(mm) {
  activePaperMm = (mm === 80) ? 80 : 58;
  COLS = (activePaperMm === 80) ? 42 : 32;
  const paper = document.getElementById('receiptPaper');
  paper.classList.remove('paper-58','paper-80');
  paper.classList.add('paper-' + activePaperMm);
  document.getElementById('paperInfo').textContent =
    activePaperMm + 'mm \u00B7 ' + COLS + ' karakter/baris';
}

/* Saat template berubah */
async function onTemplateChange(tplId) {
  if (!tplId) return;
  try {
    const res  = await fetch(APP_URL + 'template/fields/' + tplId);
    const json = await res.json();
    if (json.status !== 'ok') return;

    activeTplEls  = json.elements || [];
    activeTplType = json.template_type || 'classic';
    multiplyDefs  = [];

    applyPaperSize(json.paper_width || 58);
    applySystemFields(activeTplEls, activeTplType);

    // Date format info
    const dateEl = activeTplEls.find(e => e.label === 'date' && e.date_format);
    const fmt    = dateEl ? dateEl.date_format : 'd/m/Y H:i';
    document.getElementById('date_format_info').innerHTML =
      '<span class="date-format-badge">Format: ' + fmt + '</span>';

    if (activeTplType === 'flexible') {
      document.getElementById('dynamicSection').style.display = '';
      document.getElementById('classicSection').style.display = 'none';
      document.getElementById('summarySection').style.display = 'none';
      renderDynamicFields(activeTplEls);
    } else {
      document.getElementById('dynamicSection').style.display = 'none';
      document.getElementById('classicSection').style.display = '';
      document.getElementById('summarySection').style.display = '';
      renderItemList();
    }
    schedulePreview();
  } catch(e) { console.error(e); }
}

function resolveInputType(itype) {
  switch (itype) {
    case 'datetime':     return {type:'text',   isDate:true};
    case 'datetime_min': return {type:'text',   isDate:true};
    case 'date':         return {type:'text',   isDate:true};
    case 'number':       return {type:'number', isDate:false};
    default:             return {type:'text',   isDate:false};
  }
}

function makeDateInput(fieldName, itype, val) {
  const isDateOnly = (itype === 'date');
  const isSeconds  = (itype === 'datetime');
  if (isDateOnly) {
    const dtVal = val ? parseDMYtoISO(val, true) : '';
    return '<div style="display:flex;gap:6px;align-items:center;flex-wrap:wrap;">'
      + '<input type="date" class="form-control" style="flex:1;min-width:130px;"'
      + ' value="' + escH(dtVal) + '"'
      + ' onchange="onDatePickChange(\'' + fieldName + '\',\'date\',this.value)">'
      + '<span class="date-format-badge" id="dtdisp_' + fieldName + '" style="font-size:11px;">' + escH(val||'') + '</span>'
      + '</div>';
  } else {
    const step  = isSeconds ? ' step="1"' : '';
    const dtVal = val ? parseDMYtoISO(val, false) : '';
    return '<div style="display:flex;gap:6px;align-items:center;flex-wrap:wrap;">'
      + '<input type="datetime-local" class="form-control" style="flex:1;min-width:160px;"'
      + step
      + ' value="' + escH(dtVal) + '"'
      + ' onchange="onDatePickChange(\'' + fieldName + '\',\'' + itype + '\',this.value)">'
      + '<span class="date-format-badge" id="dtdisp_' + fieldName + '" style="font-size:11px;">' + escH(val||'') + '</span>'
      + '</div>';
  }
}

function parseDMYtoISO(s, dateOnly) {
  if (!s) return '';
  const parts  = s.trim().split(' ');
  const dparts = (parts[0]||'').split('/');
  if (dparts.length < 3) return '';
  const iso = dparts[2]+'-'+dparts[1].padStart(2,'0')+'-'+dparts[0].padStart(2,'0');
  if (dateOnly) return iso;
  return iso + 'T' + (parts[1]||'00:00');
}

function isoToDMY(isoVal, itype) {
  if (!isoVal) return '';
  const [datePart, timePart] = isoVal.split('T');
  if (!datePart) return '';
  const [y,m,d] = datePart.split('-');
  if (itype === 'date') return d+'/'+m+'/'+y;
  const t = timePart||'00:00';
  if (itype === 'datetime') {
    const segs = t.split(':'); while(segs.length<3) segs.push('00');
    return d+'/'+m+'/'+y+' '+segs.join(':');
  }
  const [hh,mm2] = t.split(':');
  return d+'/'+m+'/'+y+' '+(hh||'00')+':'+(mm2||'00');
}

function onDatePickChange(fieldName, itype, isoVal) {
  const display = isoToDMY(isoVal, itype);
  customFieldVals[fieldName] = display;
  const disp = document.getElementById('dtdisp_'+fieldName);
  if (disp) disp.textContent = display;
  recalcMultiply();
  schedulePreview();
}

function renderDynamicFields(elements) {
  const container         = document.getElementById('dynamicFields');
  const multiplyContainer = document.getElementById('multiplyResults');
  container.innerHTML         = '';
  multiplyContainer.innerHTML = '';
  multiplyDefs = [];

  [...elements].sort((a,b)=>(a.y||0)-(b.y||0)).forEach(el => {
    const type = el.element_type;

    if (type === 'input') {
      const itype = el.input_type||'text';
      const val   = customFieldVals[el.input_name] || '';
      const div   = document.createElement('div');
      div.className = 'form-group';
      if (['datetime','datetime_min','date'].includes(itype)) {
        div.innerHTML = '<label>' + escH(el.input_label||el.input_name||'Field') + '</label>'
          + makeDateInput(el.input_name, itype, val);
      } else {
        const ri = resolveInputType(itype);
        div.innerHTML = '<label>' + escH(el.input_label||el.input_name||'Field') + '</label>'
          + '<input type="' + ri.type + '" class="form-control"'
          + ' name="cf_' + escH(el.input_name) + '"'
          + ' id="cf_' + escH(el.input_name) + '"'
          + ' value="' + escH(val) + '"'
          + ' placeholder="' + escH(el.input_label||'') + '"'
          + ' oninput="onCfChange(\'' + el.input_name + '\',this.value)">';
      }
      container.appendChild(div);

    } else if (type === 'row2') {
      const c1  = el.col1||{}, c2 = el.col2||{};
      const v1  = customFieldVals[c1.input_name]||'';
      const v2  = customFieldVals[c2.input_name]||'';
      const d1  = ['datetime','datetime_min','date'].includes(c1.input_type||'text');
      const d2  = ['datetime','datetime_min','date'].includes(c2.input_type||'text');
      const ri1 = resolveInputType(c1.input_type||'text');
      const ri2 = resolveInputType(c2.input_type||'text');
      const div = document.createElement('div');
      div.className = 'dyn-row2';
      div.innerHTML =
        '<div class="form-group" style="flex:' + (c1.width||50) + '">'
        + '<label>' + escH(c1.input_label||c1.input_name||'Kol 1') + '</label>'
        + (d1 ? makeDateInput(c1.input_name, c1.input_type, v1)
              : '<input type="' + ri1.type + '" class="form-control"'
                + ' name="cf_' + escH(c1.input_name) + '" id="cf_' + escH(c1.input_name) + '"'
                + ' value="' + escH(v1) + '" placeholder="' + escH(c1.input_label||'') + '"'
                + ' oninput="onCfChange(\'' + c1.input_name + '\',this.value)">')
        + '</div>'
        + '<div class="form-group" style="flex:' + (c2.width||50) + '">'
        + '<label>' + escH(c2.input_label||c2.input_name||'Kol 2') + '</label>'
        + (d2 ? makeDateInput(c2.input_name, c2.input_type, v2)
              : '<input type="' + ri2.type + '" class="form-control"'
                + ' name="cf_' + escH(c2.input_name) + '" id="cf_' + escH(c2.input_name) + '"'
                + ' value="' + escH(v2) + '" placeholder="' + escH(c2.input_label||'') + '"'
                + ' oninput="onCfChange(\'' + c2.input_name + '\',this.value)">')
        + '</div>';
      container.appendChild(div);

    } else if (type === 'multiply') {
      multiplyDefs.push(el);
      const div = document.createElement('div');
      div.className = 'multiply-result';
      div.id = 'mr_' + el.id;
      div.innerHTML = '<span class="mr-label">' + escH(el.display_label||'Hasil') + '</span>'
        + '<span class="mr-value" id="mrv_' + el.id + '">0</span>';
      multiplyContainer.appendChild(div);
    }
  });
  recalcMultiply();
}

function onCfChange(fieldName, val) {
  customFieldVals[fieldName] = val;
  recalcMultiply();
  schedulePreview();
}

function recalcMultiply() {
  let grandTotal = 0;
  multiplyDefs.forEach(el => {
    const a = parseFloat(customFieldVals[el.input_a]||0);
    const b = parseFloat(customFieldVals[el.input_b]||0);
    const res = a * b;
    grandTotal += res;
    const ev = document.getElementById('mrv_'+el.id);
    if (ev) ev.textContent = formatNumber(res, el.format||'rupiah', el.prefix||'');
  });
  document.getElementById('hGrandTotal').value = grandTotal;
  document.getElementById('hSubtotal').value   = grandTotal;
}

function formatNumber(num, format, prefix) {
  switch (format) {
    case 'rupiah':     return 'Rp ' + num.toLocaleString('id-ID');
    case 'number_sep': return prefix + num.toLocaleString('id-ID');
    case 'number':     return prefix + Math.round(num).toString();
    default:           return prefix + (num % 1 === 0 ? Math.round(num).toString() : num.toFixed(2));
  }
}

function renderItemList() {
  const list = document.getElementById('itemList');
  list.innerHTML = '';
  classicItems.forEach((item, idx) => {
    const sub = (parseFloat(item.qty)||0)*(parseFloat(item.price)||0);
    const row = document.createElement('div');
    row.className = 'item-row';
    row.innerHTML = '<div class="col-name"><input type="text" class="form-control" placeholder="Nama item" value="' + escH(item.name) + '" oninput="updItem(' + idx + ',\'name\',this.value)"></div>'
      + '<div class="col-qty"><input type="number" class="form-control" min="1" value="' + (item.qty||1) + '" oninput="updItem(' + idx + ',\'qty\',parseFloat(this.value)||1)"></div>'
      + '<div class="col-price"><input type="number" class="form-control" min="0" value="' + (item.price||0) + '" oninput="updItem(' + idx + ',\'price\',parseFloat(this.value)||0)"></div>'
      + '<div class="col-sub">' + fmtRp(sub) + '</div>'
      + '<div class="col-del"><button type="button" class="btn btn-danger btn-sm" onclick="removeItem(' + idx + ')">\u2715</button></div>';
    list.appendChild(row);
  });
  recalcClassic();
}

function addItem()       { classicItems.push({name:'',qty:1,price:0}); renderItemList(); }
function removeItem(idx) { if(classicItems.length<=1){alert('Min 1 item!');return;} classicItems.splice(idx,1); renderItemList(); }
function updItem(idx,k,v){ classicItems[idx][k]=v; recalcClassic(); const rows=document.querySelectorAll('.item-row'); if(rows[idx]) rows[idx].querySelector('.col-sub').textContent=fmtRp((parseFloat(classicItems[idx].qty)||0)*(parseFloat(classicItems[idx].price)||0)); schedulePreview(); }

function recalcClassic() {
  const sub  = classicItems.reduce((s,i)=>s+(parseFloat(i.qty)||0)*(parseFloat(i.price)||0),0);
  const disc = parseFloat(document.getElementById('inp_discount').value)||0;
  const tax  = parseFloat(document.getElementById('inp_tax').value)||0;
  const tot  = sub-disc+tax;
  document.getElementById('disp_subtotal').textContent = fmtRp(sub);
  document.getElementById('disp_total').textContent    = fmtRp(tot);
  document.getElementById('hSubtotal').value   = sub;
  document.getElementById('hGrandTotal').value = tot;
  schedulePreview();
}

function schedulePreview() {
  document.getElementById('previewStatus').style.color = '#FF9800';
  document.getElementById('previewStatus').textContent = '\u25CF Mengetik...';
  clearTimeout(previewTimer);
  previewTimer = setTimeout(doPreview, 450);
}

async function doPreview() {
  const statusEl = document.getElementById('previewStatus');
  const loadEl   = document.getElementById('previewLoading');
  statusEl.style.color = '#2196F3';
  statusEl.textContent = '\u25CF Memuat...';
  loadEl.style.display = 'block';

  const tplId   = parseInt(document.getElementById('inp_template').value)||0;
  const storeId = parseInt(document.getElementById('inp_store').value)||1;
  if (!tplId) { loadEl.style.display='none'; return; }

  const invoiceVal = document.getElementById('inp_invoice')?.value  || '';
  const cashierVal = document.getElementById('inp_cashier')?.value  || '';
  const dateVal    = document.getElementById('inp_trx_date')?.value || new Date().toISOString().slice(0,16);
  const discVal    = parseFloat(document.getElementById('inp_discount')?.value)||0;
  const taxVal     = parseFloat(document.getElementById('inp_tax')?.value)||0;
  const noteVal    = document.getElementById('inp_note')?.value || '';

  try {
    const res = await fetch(APP_URL + 'receipt/preview_data', {
      method:'POST', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({
        template_id: tplId, store_id: storeId,
        invoice_no: invoiceVal, cashier: cashierVal, trx_date: dateVal,
        discount: discVal, tax: taxVal, note: noteVal,
        items: classicItems, custom_fields: customFieldVals,
      }),
    });
    const json = await res.json();
    if (json.status !== 'ok') { loadEl.style.display='none'; return; }
    renderPreviewHTML(json.elements, json.data);
  } catch(e) { console.error(e); }
  finally {
    loadEl.style.display = 'none';
    statusEl.style.color = '#4CAF50';
    statusEl.textContent = '\u25CF Live';
  }
}

function renderPreviewHTML(elements, data) {
  const paper  = document.getElementById('receiptPaper');
  const sorted = [...elements].sort((a,b)=>(parseInt(a.y)||0)-(parseInt(b.y)||0));
  let html = '';
  sorted.forEach(el => {
    const type   = el.element_type;
    const align  = el.align || 'left';
    const bold   = el.bold  ? ' r-bold' : '';
    const fsize  = parseInt(el.font_size)||1;
    const fsClass= fsize===2?' r-size2':(fsize===3?' r-size3':'');
    const cls    = 'r-'+align+bold+fsClass;
    if (type === 'line')   { html += '<span class="r-line r-left">'+'\u2500'.repeat(COLS)+'</span>'; return; }
    if (type === 'spacer') { html += '<span class="r-left">&nbsp;</span>'; return; }

    /* ── STORE HEADER ── */
    if (type === 'store_header') {
      const al   = el.header_align || 'center';
      const repl = (s) => s ? Object.keys(data).reduce((acc,k)=>acc.replace(new RegExp('\\{\\{'+k+'\\}\\}','g'),data[k]||''),s) : '';
      const lt   = repl(el.logo_text    ||'');
      const cn   = repl(el.company_name ||'');
      const a1   = repl(el.address_line1||'');
      const a2   = repl(el.address_line2||'');
      if (lt) html += `<span class="r-center r-bold r-size2">${escH(lt)}</span>`;
      if (cn) wrapText(cn, COLS).forEach(l => html += `<span class="r-${al}">${escH(l)}</span>`);
      if (a1) wrapText(a1, COLS).forEach(l => html += `<span class="r-${al}">${escH(l)}</span>`);
      if (a2) wrapText(a2, COLS).forEach(l => html += `<span class="r-${al}">${escH(l)}</span>`);
      if (el.npwp)  html += `<span class="r-${al}">NPWP: ${escH(el.npwp)}</span>`;
      if (el.phone) html += `<span class="r-${al}">Telp: ${escH(el.phone)}</span>`;
      if (el.store_code) html += `<span class="r-${al}">${escH(repl(el.store_code))}</span>`;
      if (el.show_divider) html += `<span class="r-line r-left">${'\u2500'.repeat(COLS)}</span>`;
      return;
    }

    if (type === 'text') {
      let val = el.value || '';
      Object.keys(data).forEach(k => { val = val.replace(new RegExp('\\{\\{'+k+'\\}\\}','g'), data[k]||''); });
      if (el.label === 'items') {
        val.split('\n').forEach(line => { if(line) html += '<span class="r-left">'+escH(line)+'</span>'; });
      } else {
        wrapText(val, Math.floor(COLS/Math.max(1,fsize-0.5))).forEach(l => { html += '<span class="'+cls+'">'+escH(l)+'</span>'; });
      }
      return;
    }
    if (type === 'input') {
      const iname = el.input_name || el.label || '';
      const raw   = data[iname] !== undefined ? data[iname] : (customFieldVals[iname]||'');
      const disp  = el.input_label ? el.input_label+': '+raw : raw;
      html += '<span class="'+cls+'">'+escH(disp)+'</span>';
      return;
    }
    if (type === 'row2') {
      const c1=el.col1||{}, c2=el.col2||{};
      const v1=customFieldVals[c1.input_name||'']||'', v2=customFieldVals[c2.input_name||'']||'';
      const w1=Math.round(COLS*(c1.width||50)/100), w2=COLS-w1;
      html += '<span class="r-left">'+escH(String(v1).substring(0,w1).padEnd(w1)+String(v2).substring(0,w2).padStart(w2))+'</span>';
      return;
    }
    if (type === 'multiply') {
      const a=parseFloat(customFieldVals[el.input_a||'']||0), b=parseFloat(customFieldVals[el.input_b||'']||0);
      const fmt=formatNumber(a*b, el.format||'rupiah', el.prefix||'');
      const lbl=(el.display_label||'Total').padEnd(16);
      html += '<span class="'+cls+'">'+escH(lbl+fmt)+'</span>';
      return;
    }
  });
  paper.innerHTML = html || '<span style="color:#ccc">Template kosong</span>';
}

function wrapText(str, w) { if(!str)return['']; const out=[]; for(let i=0;i<str.length;i+=w)out.push(str.slice(i,i+w)); return out; }
function escH(s) { return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
function fmtRp(n) { return 'Rp ' + Math.round(n).toLocaleString('id-ID'); }

function setDateNow() {
  const now=new Date(), pad=n=>String(n).padStart(2,'0');
  const el = document.getElementById('inp_trx_date');
  if (el) el.value = now.getFullYear()+'-'+pad(now.getMonth()+1)+'-'+pad(now.getDate())+'T'+pad(now.getHours())+':'+pad(now.getMinutes());
  schedulePreview();
}

function submitForm() {
  if (activeTplType==='classic' && !classicItems.every(i=>i.name.trim()!=='')) {
    alert('Nama item tidak boleh kosong!'); return;
  }
  document.getElementById('hItems').value = JSON.stringify(classicItems);
  document.getElementById('hCF').value    = JSON.stringify(customFieldVals);
  document.getElementById('trxForm').submit();
}

(function() {
  const sel = document.getElementById('inp_template');
  if (sel && sel.value) onTemplateChange(sel.value);
})();
</script>
