<?php
$defJson = $def ? json_encode([
  'id' => $def['id'], 'name' => $def['name'], 'description' => $def['description'],
  'data_source' => $def['data_source'], 'chart_type' => $def['chart_type'],
  'group_by' => $def['group_by'], 'columns' => $def['columns'], 'filters' => $def['filters'],
  'pivot' => $def['pivot'], 'options' => $def['options'], 'visibility' => $def['visibility'],
  'is_system' => $def['is_system'],
], JSON_UNESCAPED_UNICODE) : 'null';
$fieldList = [];
foreach ($fields as $k => $d) $fieldList[] = ['key'=>$k,'label'=>$d['label'],'type'=>$d['type'],'group'=>$d['group'] ?? 'Lain','agg'=>!empty($d['agg'])];
?>
<div class="row g-3">
  <!-- ============ PANEL KONFIGURASI ============ -->
  <div class="col-xl-4">
    <div class="card mb-3">
      <div class="card-header"><i class="bi bi-sliders me-1"></i>Konfigurasi Laporan</div>
      <div class="card-body">
        <div class="mb-2"><label class="form-label required" for="rbNama">Nama Laporan</label>
          <input type="text" class="form-control form-control-sm" id="rbNama" maxlength="180" value="<?= attr($def['name'] ?? '') ?>"></div>
        <div class="mb-2"><label class="form-label" for="rbDesk">Deskripsi</label>
          <input type="text" class="form-control form-control-sm" id="rbDesk" maxlength="500" value="<?= attr($def['description'] ?? '') ?>"></div>
        <div class="mb-2"><label class="form-label" for="rbSumber">1. Sumber Data</label>
          <select class="form-select form-select-sm" id="rbSumber">
            <?php foreach ($sources as $k => $s): ?>
              <option value="<?= attr($k) ?>" <?= $source === $k ? 'selected' : '' ?>><?= e($s['label']) ?></option>
            <?php endforeach; ?>
          </select>
          <div class="form-text" id="rbSumberDesk"><?= e($sources[$source]['deskripsi']) ?></div></div>
        <div class="row g-2">
          <div class="col-6"><label class="form-label" for="rbChart">Jenis Chart</label>
            <select class="form-select form-select-sm" id="rbChart">
              <?php foreach ($chartTypes as $k => $v): ?>
                <option value="<?= attr($k) ?>" <?= ($def['chart_type'] ?? 'none') === $k ? 'selected':'' ?>><?= e($v) ?></option>
              <?php endforeach; ?></select></div>
          <div class="col-6"><label class="form-label" for="rbVis">Berbagi</label>
            <select class="form-select form-select-sm" id="rbVis">
              <option value="private" <?= ($def['visibility'] ?? 'private')==='private'?'selected':'' ?>>Pribadi</option>
              <option value="shared" <?= ($def['visibility'] ?? '')==='shared'?'selected':'' ?>>Dibagikan</option>
              <option value="public" <?= ($def['visibility'] ?? '')==='public'?'selected':'' ?>>Publik</option>
            </select></div>
          <div class="col-6"><label class="form-label" for="rbAsOf">Tanggal Pelaporan</label>
            <input type="date" class="form-control form-control-sm" id="rbAsOf" value="<?= attr($def['options']['as_of'] ?? App\Core\Dates::today()) ?>"></div>
          <div class="col-6"><label class="form-label" for="rbLimit">Batas Baris</label>
            <input type="number" class="form-control form-control-sm" id="rbLimit" min="10" max="5000" value="<?= (int)($def['options']['limit'] ?? 500) ?>"></div>
          <div class="col-12"><div class="form-check">
            <input class="form-check-input" type="checkbox" id="rbSubtotal" <?= !empty($def['options']['subtotal']) ? 'checked':'' ?>>
            <label class="form-check-label small" for="rbSubtotal">Tampilkan subtotal per kelompok pertama</label></div></div>
        </div>
      </div>
    </div>

    <div class="card mb-3">
      <div class="card-header"><i class="bi bi-diagram-2 me-1"></i>2. Pengelompokan (Grouping)</div>
      <div class="card-body">
        <div id="rbGroupChips" class="mb-2"></div>
        <select class="form-select form-select-sm" id="rbGroupAdd"><option value="">+ Tambah pengelompokan…</option></select>
        <div class="form-text">Kolom non-agregat akan otomatis diringkas bila pengelompokan aktif.</div>
      </div>
    </div>

    <div class="card mb-3">
      <div class="card-header"><i class="bi bi-table me-1"></i>3. Kolom Laporan</div>
      <div class="card-body">
        <div class="rb-row cols text-body-secondary small fw-semibold d-none d-lg-grid">
          <div>Field</div><div>Agregasi</div><div>Urutkan</div><div></div></div>
        <div id="rbCols"></div>
        <select class="form-select form-select-sm mt-2" id="rbColAdd"><option value="">+ Tambah kolom…</option></select>
      </div>
    </div>

    <div class="card mb-3">
      <div class="card-header"><i class="bi bi-funnel me-1"></i>4. Filter</div>
      <div class="card-body">
        <div id="rbFilters"></div>
        <button class="btn btn-sm btn-outline-secondary w-100 mt-2" type="button" id="rbFilterAdd"><i class="bi bi-plus-lg me-1"></i>Tambah Filter</button>
      </div>
    </div>

    <div class="card mb-3">
      <div class="card-header"><i class="bi bi-grid-3x3 me-1"></i>5. Pivot (opsional)</div>
      <div class="card-body row g-2">
        <div class="col-12"><label class="form-label" for="rbPivotCol">Kolom Pivot (menjadi judul kolom)</label>
          <select class="form-select form-select-sm" id="rbPivotCol"><option value="">— Tanpa pivot —</option></select></div>
        <div class="col-7"><label class="form-label" for="rbPivotVal">Nilai</label>
          <select class="form-select form-select-sm" id="rbPivotVal"><option value="">—</option></select></div>
        <div class="col-5"><label class="form-label" for="rbPivotAgg">Agregasi</label>
          <select class="form-select form-select-sm" id="rbPivotAgg">
            <?php foreach (['sum'=>'Jumlah','count'=>'Cacah','avg'=>'Rata-rata','max'=>'Maks','min'=>'Min'] as $k=>$v): ?>
              <option value="<?= $k ?>"><?= e($v) ?></option><?php endforeach; ?></select></div>
      </div>
    </div>

    <div class="d-grid gap-2">
      <button class="btn btn-primary" type="button" id="rbJalankan"><i class="bi bi-play-fill me-1"></i>Jalankan Laporan</button>
      <div class="btn-group">
        <?php if (can('report_builder','create')): ?>
          <button class="btn btn-outline-primary" type="button" id="rbSimpan"><i class="bi bi-save me-1"></i>Simpan Template</button>
        <?php endif; ?>
        <?php if ($def && can('report_builder','create')): ?>
          <form method="post" action="<?= url('/pembuat-laporan/'.(int)$def['id'].'/duplikat') ?>" class="d-inline"><?= csrf() ?>
            <button class="btn btn-outline-secondary" type="submit"><i class="bi bi-files me-1"></i>Duplikat</button></form>
        <?php endif; ?>
      </div>
      <?php if (can('report_builder','export')): ?>
      <div class="btn-group">
        <button class="btn btn-outline-success btn-sm" type="button" onclick="rbExport('xlsx')"><i class="bi bi-file-earmark-excel me-1"></i>Excel</button>
        <button class="btn btn-outline-success btn-sm" type="button" onclick="rbExport('csv')">CSV</button>
        <button class="btn btn-outline-danger btn-sm" type="button" onclick="rbExport('pdf')"><i class="bi bi-file-earmark-pdf me-1"></i>PDF</button>
        <button class="btn btn-outline-dark btn-sm" type="button" onclick="rbExport('print')"><i class="bi bi-printer"></i></button>
      </div>
      <?php endif; ?>
    </div>
  </div>

  <!-- ============ HASIL ============ -->
  <div class="col-xl-8">
    <div class="card mb-3" id="rbChartCard" style="display:none">
      <div class="card-header"><i class="bi bi-bar-chart me-1"></i>Grafik</div>
      <div class="card-body"><div class="chart-box lg"><canvas id="rbChartCanvas"></canvas></div></div>
    </div>
    <div class="card">
      <div class="card-header">
        <i class="bi bi-table me-1"></i>Hasil Laporan
        <span class="text-body-secondary fw-normal ms-1" id="rbInfo">Belum dijalankan</span>
      </div>
      <div class="table-wrap" style="max-height:640px">
        <table class="table table-sm table-hover table-sticky mb-0" id="rbTabel">
          <thead><tr><th class="text-body-secondary fw-normal">Klik "Jalankan Laporan" untuk menampilkan hasil.</th></tr></thead>
          <tbody></tbody><tfoot></tfoot>
        </table>
      </div>
    </div>
  </div>
</div>

<form id="rbFormExport" method="post" action="<?= url('/pembuat-laporan/ekspor') ?>" target="_blank" class="d-none">
  <?= csrf() ?><input type="hidden" name="definisi" id="rbExportDef"><input type="hidden" name="format" id="rbExportFmt">
</form>

<?php viewStart('scripts'); ?>
<script>
(function () {
  let FIELDS = <?= json_encode($fieldList, JSON_UNESCAPED_UNICODE) ?>;
  const OPERATORS = <?= json_encode($operators, JSON_UNESCAPED_UNICODE) ?>;
  const AGGREGATES = <?= json_encode($aggregates, JSON_UNESCAPED_UNICODE) ?>;
  const SOURCES = <?= json_encode($sources, JSON_UNESCAPED_UNICODE) ?>;
  const DEF = <?= $defJson ?>;
  let templateId = DEF ? DEF.id : null;
  let cols = [], filters = [], groups = [];

  const el = id => document.getElementById(id);
  const fieldByKey = k => FIELDS.find(f => f.key === k);

  function optionsHtml(placeholder, exclude) {
    const byGroup = {};
    FIELDS.forEach(f => { (byGroup[f.group] = byGroup[f.group] || []).push(f); });
    let h = '<option value="">' + placeholder + '</option>';
    Object.keys(byGroup).forEach(g => {
      h += '<optgroup label="' + g + '">';
      byGroup[g].forEach(f => {
        if (exclude && exclude.includes(f.key)) return;
        h += '<option value="' + f.key + '">' + f.label + '</option>';
      });
      h += '</optgroup>';
    });
    return h;
  }

  function refreshSelectors() {
    el('rbColAdd').innerHTML = optionsHtml('+ Tambah kolom…');
    el('rbGroupAdd').innerHTML = optionsHtml('+ Tambah pengelompokan…', groups);
    el('rbPivotCol').innerHTML = optionsHtml('— Tanpa pivot —');
    el('rbPivotVal').innerHTML = optionsHtml('—');
  }

  function renderGroups() {
    el('rbGroupChips').innerHTML = groups.length
      ? groups.map((g, i) => {
          const f = fieldByKey(g);
          return '<span class="rb-chip">' + (f ? f.label : g) +
                 '<button type="button" data-gdel="' + i + '" aria-label="Hapus">&times;</button></span>';
        }).join('')
      : '<span class="text-body-secondary small">Tidak ada pengelompokan (laporan detail).</span>';
  }

  function renderCols() {
    el('rbCols').innerHTML = cols.map((c, i) => {
      const f = fieldByKey(c.field);
      let aggOpts = '';
      Object.keys(AGGREGATES).forEach(k => {
        aggOpts += '<option value="' + k + '"' + (c.aggregate === k ? ' selected' : '') + '>' + AGGREGATES[k] + '</option>';
      });
      return '<div class="rb-row cols">' +
        '<div><span class="badge bg-light text-dark border w-100 text-start text-truncate">' + (f ? f.label : c.field) + '</span></div>' +
        '<div><select class="form-select form-select-sm" data-cagg="' + i + '">' + aggOpts + '</select></div>' +
        '<div><select class="form-select form-select-sm" data-csort="' + i + '">' +
          '<option value=""' + (!c.sort_dir ? ' selected' : '') + '>—</option>' +
          '<option value="asc"' + (c.sort_dir === 'asc' ? ' selected' : '') + '>A→Z / Kecil→Besar</option>' +
          '<option value="desc"' + (c.sort_dir === 'desc' ? ' selected' : '') + '>Z→A / Besar→Kecil</option></select></div>' +
        '<div class="d-flex gap-1">' +
          '<button class="btn btn-sm btn-light px-1" type="button" data-cup="' + i + '" title="Naik">&uarr;</button>' +
          '<button class="btn btn-sm btn-light px-1" type="button" data-cdown="' + i + '" title="Turun">&darr;</button>' +
          '<button class="btn btn-sm btn-outline-danger px-1" type="button" data-cdel="' + i + '" title="Hapus">&times;</button>' +
        '</div></div>';
    }).join('') || '<div class="text-body-secondary small">Belum ada kolom. Tambahkan minimal satu kolom.</div>';
  }

  function renderFilters() {
    el('rbFilters').innerHTML = filters.map((f, i) => {
      let opOpts = '';
      Object.keys(OPERATORS).forEach(k => {
        opOpts += '<option value="' + k + '"' + (f.operator === k ? ' selected' : '') + '>' + OPERATORS[k].label + '</option>';
      });
      const args = OPERATORS[f.operator] ? OPERATORS[f.operator].args : 1;
      const fd = fieldByKey(f.field);
      const inputType = fd && fd.type === 'date' ? 'date' : 'text';
      return '<div class="rb-row filters">' +
        '<div><select class="form-select form-select-sm" data-fconj="' + i + '"' + (i === 0 ? ' disabled' : '') + '>' +
          '<option value="AND"' + (f.conjunction !== 'OR' ? ' selected' : '') + '>DAN</option>' +
          '<option value="OR"' + (f.conjunction === 'OR' ? ' selected' : '') + '>ATAU</option></select></div>' +
        '<div><select class="form-select form-select-sm" data-ffield="' + i + '">' + optionsHtml('— Pilih field —').replace('value="' + f.field + '"', 'value="' + f.field + '" selected') + '</select></div>' +
        '<div><select class="form-select form-select-sm" data-fop="' + i + '">' + opOpts + '</select></div>' +
        '<div>' + (args >= 1 ? '<input type="' + inputType + '" class="form-control form-control-sm" data-fv1="' + i + '" value="' + (f.value1 || '') + '" placeholder="Nilai">' : '') + '</div>' +
        '<div>' + (args >= 2 ? '<input type="' + inputType + '" class="form-control form-control-sm" data-fv2="' + i + '" value="' + (f.value2 || '') + '" placeholder="Sampai">' : '') + '</div>' +
        '<div><button class="btn btn-sm btn-outline-danger px-1" type="button" data-fdel="' + i + '">&times;</button></div>' +
      '</div>';
    }).join('') || '<div class="text-body-secondary small">Belum ada filter — seluruh data akan ditampilkan.</div>';
  }

  // ------------------------------------------------- event delegation
  document.addEventListener('click', function (e) {
    const t = e.target;
    if (t.dataset.gdel !== undefined) { groups.splice(+t.dataset.gdel, 1); renderGroups(); refreshSelectors(); }
    if (t.dataset.cdel !== undefined) { cols.splice(+t.dataset.cdel, 1); renderCols(); }
    if (t.dataset.fdel !== undefined) { filters.splice(+t.dataset.fdel, 1); renderFilters(); }
    if (t.dataset.cup !== undefined) { const i = +t.dataset.cup; if (i > 0) { [cols[i-1], cols[i]] = [cols[i], cols[i-1]]; renderCols(); } }
    if (t.dataset.cdown !== undefined) { const i = +t.dataset.cdown; if (i < cols.length-1) { [cols[i+1], cols[i]] = [cols[i], cols[i+1]]; renderCols(); } }
  });
  document.addEventListener('change', function (e) {
    const t = e.target;
    if (t.dataset.cagg !== undefined) cols[+t.dataset.cagg].aggregate = t.value;
    if (t.dataset.csort !== undefined) { cols[+t.dataset.csort].sort_dir = t.value; cols[+t.dataset.csort].sort_priority = t.value ? 1 : 0; }
    if (t.dataset.ffield !== undefined) { filters[+t.dataset.ffield].field = t.value; renderFilters(); }
    if (t.dataset.fop !== undefined) { filters[+t.dataset.fop].operator = t.value; renderFilters(); }
    if (t.dataset.fconj !== undefined) filters[+t.dataset.fconj].conjunction = t.value;
  });
  document.addEventListener('input', function (e) {
    const t = e.target;
    if (t.dataset.fv1 !== undefined) filters[+t.dataset.fv1].value1 = t.value;
    if (t.dataset.fv2 !== undefined) filters[+t.dataset.fv2].value2 = t.value;
  });

  el('rbColAdd').addEventListener('change', function () {
    if (!this.value) return;
    cols.push({ field: this.value, aggregate: 'none', sort_dir: '', sort_priority: 0 });
    this.value = ''; renderCols();
  });
  el('rbGroupAdd').addEventListener('change', function () {
    if (!this.value) return;
    if (!groups.includes(this.value)) groups.push(this.value);
    this.value = ''; renderGroups(); refreshSelectors();
  });
  el('rbFilterAdd').addEventListener('click', function () {
    filters.push({ field: FIELDS[0] ? FIELDS[0].key : '', operator: 'eq', value1: '', value2: '', conjunction: 'AND' });
    renderFilters();
  });

  el('rbSumber').addEventListener('change', function () {
    const src = this.value;
    el('rbSumberDesk').textContent = SOURCES[src] ? SOURCES[src].deskripsi : '';
    SP.get(SP.url('/pembuat-laporan/field'), { sumber: src }).then(res => {
      if (!res.sukses) return;
      FIELDS = res.fields; cols = []; filters = []; groups = [];
      refreshSelectors(); renderCols(); renderFilters(); renderGroups();
      SP.toast('Sumber data diganti. Silakan pilih kolom baru.', 'info');
    });
  });

  function definisi() {
    return {
      name: el('rbNama').value || 'Laporan Tanpa Nama',
      description: el('rbDesk').value,
      data_source: el('rbSumber').value,
      chart_type: el('rbChart').value,
      visibility: el('rbVis').value,
      group_by: groups,
      columns: cols,
      filters: filters.filter(f => f.field),
      pivot: el('rbPivotCol').value && el('rbPivotVal').value
        ? { column: el('rbPivotCol').value, value: el('rbPivotVal').value, aggregate: el('rbPivotAgg').value } : null,
      options: {
        as_of: el('rbAsOf').value,
        limit: parseInt(el('rbLimit').value || '500', 10),
        subtotal: el('rbSubtotal').checked,
      },
    };
  }

  let chart = null;
  function jalankan() {
    if (!cols.length) { SP.toast('Tambahkan minimal satu kolom laporan.', 'warning'); return; }
    SP.loading(true);
    SP.post(SP.url('/pembuat-laporan/jalankan'), { definisi: JSON.stringify(definisi()) }).then(res => {
      SP.loading(false);
      if (!res.sukses) { SP.toast(res.pesan || 'Laporan gagal dijalankan.', 'danger'); return; }
      const tbl = el('rbTabel');
      tbl.querySelector('thead').innerHTML = '<tr>' + res.kolom.map(c =>
        '<th class="' + (['money','int','dec','pct'].includes(c.type) ? 'num' : '') + '">' + c.label + '</th>').join('') + '</tr>';
      tbl.querySelector('tbody').innerHTML = res.baris.length
        ? res.baris.map(r => '<tr>' + res.kolom.map(c => {
            const cell = r[c.alias] || { txt: '-', raw: null };
            const neg = ['money','dec'].includes(c.type) && parseFloat(cell.raw) < 0;
            return '<td class="' + (['money','int','dec','pct'].includes(c.type) ? 'num' : '') + (neg ? ' text-negative' : '') + '">' + cell.txt + '</td>';
          }).join('') + '</tr>').join('')
        : '<tr><td colspan="' + res.kolom.length + '"><div class="empty-state"><i class="bi bi-inbox"></i>Tidak ada data yang sesuai.</div></td></tr>';
      tbl.querySelector('tfoot').innerHTML = res.baris.length
        ? '<tr>' + res.kolom.map((c, i) => '<td class="' + (['money','int','dec','pct'].includes(c.type) ? 'num' : '') + '">' +
            (i === 0 ? 'TOTAL' : (res.total[c.alias] || '')) + '</td>').join('') + '</tr>' : '';
      el('rbInfo').textContent = 'Menampilkan ' + SP.nf(res.ditampilkan) + ' dari ' + SP.nf(res.jumlah_baris) + ' baris' +
        (res.terpotong ? ' (dibatasi)' : '');

      if (res.chart && res.chart.datasets.length) {
        el('rbChartCard').style.display = '';
        const type = res.chart.type === 'horizontalBar' ? 'bar' : (res.chart.type === 'area' ? 'line' : (res.chart.type === 'stackedBar' ? 'bar' : res.chart.type));
        chart = SP.makeChart('rbChartCanvas', {
          type: type,
          data: { labels: res.chart.labels, datasets: res.chart.datasets.map((d, i) => ({
            label: d.label, data: d.data,
            backgroundColor: ['pie','doughnut'].includes(type) ? d.data.map((_, j) => SP.palette[j % SP.palette.length]) : SP.palette[i % SP.palette.length],
            borderColor: SP.palette[i % SP.palette.length],
            fill: res.chart.type === 'area', tension: .3, borderRadius: 4 })) },
          options: {
            indexAxis: res.chart.type === 'horizontalBar' ? 'y' : 'x',
            plugins: { legend: { position: 'bottom' }, tooltip: { callbacks: { label: c => c.dataset.label + ': ' + SP.rp(c.parsed.y !== undefined && c.parsed.y !== null ? c.parsed.y : c.parsed) } } },
            scales: ['pie','doughnut'].includes(type) ? {} :
              (res.chart.type === 'horizontalBar' ? { x: SP.moneyAxis } : { y: SP.moneyAxis }),
          }
        });
      } else { el('rbChartCard').style.display = 'none'; }
    }).catch(() => { SP.loading(false); SP.toast('Terjadi kesalahan jaringan.', 'danger'); });
  }

  el('rbJalankan').addEventListener('click', jalankan);
  const btnSimpan = el('rbSimpan');
  if (btnSimpan) btnSimpan.addEventListener('click', function () {
    if (!el('rbNama').value.trim()) { SP.toast('Isi nama laporan terlebih dahulu.', 'warning'); el('rbNama').focus(); return; }
    SP.loading(true);
    SP.post(SP.url('/pembuat-laporan/simpan'), { definisi: JSON.stringify(definisi()), template_id: templateId || '' }).then(res => {
      SP.loading(false);
      if (!res.sukses) { SP.toast(res.pesan, 'danger'); return; }
      SP.toast(res.pesan, 'success');
      if (!templateId && res.redirect) setTimeout(() => window.location = res.redirect, 700);
      templateId = res.id;
    });
  });

  window.rbExport = function (format) {
    el('rbExportDef').value = JSON.stringify(definisi());
    el('rbExportFmt').value = format;
    el('rbFormExport').submit();
  };

  // ------------------------------------------------- inisialisasi
  refreshSelectors();
  if (DEF) {
    cols = (DEF.columns || []).map(c => ({ field: c.field, aggregate: c.aggregate || 'none', sort_dir: c.sort_dir || '', sort_priority: c.sort_priority || 0 }));
    filters = (DEF.filters || []).map(f => ({ field: f.field, operator: f.operator || 'eq', value1: f.value1 || '', value2: f.value2 || '', conjunction: f.conjunction || 'AND' }));
    groups = DEF.group_by || [];
    if (DEF.pivot) { el('rbPivotCol').value = DEF.pivot.column || ''; el('rbPivotVal').value = DEF.pivot.value || ''; el('rbPivotAgg').value = DEF.pivot.aggregate || 'sum'; }
  }
  renderCols(); renderFilters(); renderGroups();
  if (cols.length) jalankan();
})();
</script>
<?php viewStop(); ?>
