<?php
require_once __DIR__ . '/includes/db.php';

$pageTitle  = 'Volumetrie';
$breadcrumb = [['label' => 'Volumetrie']];

$dbError = null;

// ---- Filtre ----
// Implicit, scopul e contul activ (selectat din header). Un ?account explicit în
// URL îl poate suprascrie pentru acest view (inclusiv ?account= gol = toate).
$filterAccount  = isset($_GET['account']) ? (int)$_GET['account'] : active_account_id();
$search         = trim((string)($_GET['q'] ?? ''));
$filterComplete = $_GET['vol'] ?? ''; // '', 'complete', 'incomplete'
$page           = max(1, (int)($_GET['page'] ?? 1));
$allowedPer     = [50, 100, 200];
$perPage        = (int)($_GET['per_page'] ?? 50);
if (!in_array($perPage, $allowedPer, true)) $perPage = 50;

$accounts      = [];
$products      = [];
$total         = 0;
$totalPages    = 1;
$eligibleCount = 0;          // produse care POT fi împinse la eMAG pentru contul selectat
$selectedAccount = null;

try {
    $accounts = db_select(
        "SELECT id, account_name, username, is_active, last_sync_at
         FROM emag_accounts WHERE is_active = 1 ORDER BY account_name ASC"
    );
    foreach ($accounts as $a) {
        if ((int)$a['id'] === $filterAccount) $selectedAccount = $a;
    }

    // WHERE comun: exclude produsele excluse (EAN sau categorie)
    $where  = [
        "(c.is_excluded IS NULL OR c.is_excluded = 0)",
        "(p.ean IS NULL OR p.ean NOT IN (SELECT ean FROM excluded_eans))",
    ];
    $params = [];

    if ($filterAccount > 0) {
        $where[] = 'p.emag_account_id = ?';
        $params[] = $filterAccount;
    }
    if ($search !== '') {
        $where[] = '(p.ean LIKE ? OR p.product_name LIKE ? OR p.pnk LIKE ? OR p.emag_id LIKE ?)';
        $q = '%' . $search . '%';
        array_push($params, $q, $q, $q, $q);
    }
    if ($filterComplete === 'complete') {
        $where[] = '(p.length_mm IS NOT NULL AND p.width_mm IS NOT NULL AND p.height_mm IS NOT NULL AND p.weight_g IS NOT NULL)';
    } elseif ($filterComplete === 'incomplete') {
        $where[] = '(p.length_mm IS NULL OR p.width_mm IS NULL OR p.height_mm IS NULL OR p.weight_g IS NULL)';
    }
    $whereSql = implode(' AND ', $where);

    $total = (int)db_scalar(
        "SELECT COUNT(*) FROM products p
         LEFT JOIN categories c ON c.id = p.category_id
         WHERE $whereSql",
        $params
    );
    $totalPages = max(1, (int)ceil($total / $perPage));
    if ($page > $totalPages) $page = $totalPages;
    $offset = ($page - 1) * $perPage;

    $products = db_select(
        "SELECT p.id, p.product_name, p.ean, p.pnk, p.emag_id, p.emag_account_id,
                p.length_mm, p.width_mm, p.height_mm, p.weight_g, p.volumetrie_synced_at,
                a.account_name
         FROM products p
         LEFT JOIN categories c ON c.id = p.category_id
         LEFT JOIN emag_accounts a ON a.id = p.emag_account_id
         WHERE $whereSql
         ORDER BY p.volumetrie_synced_at IS NOT NULL, p.product_name COLLATE NOCASE
         LIMIT ? OFFSET ?",
        array_merge($params, [$perPage, $offset])
    );

    // Câte produse pot fi efectiv împinse la eMAG pentru contul selectat
    if ($filterAccount > 0) {
        $eligibleCount = (int)db_scalar(
            "SELECT COUNT(*) FROM products p
             LEFT JOIN categories c ON c.id = p.category_id
             WHERE p.emag_account_id = ?
               AND p.emag_id IS NOT NULL AND p.emag_id != ''
               AND p.length_mm IS NOT NULL AND p.width_mm IS NOT NULL
               AND p.height_mm IS NOT NULL AND p.weight_g IS NOT NULL
               AND (c.is_excluded IS NULL OR c.is_excluded = 0)
               AND (p.ean IS NULL OR p.ean NOT IN (SELECT ean FROM excluded_eans))",
            [$filterAccount]
        );
    }
} catch (Throwable $ex) {
    $dbError = $ex->getMessage();
}

function vol_url(array $overrides = []): string {
    $current = [
        'account'  => $_GET['account']  ?? null,
        'q'        => $_GET['q']        ?? null,
        'vol'      => $_GET['vol']      ?? null,
        'page'     => $_GET['page']     ?? null,
        'per_page' => $_GET['per_page'] ?? null,
    ];
    $merged = array_filter(array_merge($current, $overrides), fn($v) => $v !== null && $v !== '');
    return '?' . http_build_query($merged);
}

$startRow = $total > 0 ? (($page - 1) * $perPage) + 1 : 0;
$endRow   = min($page * $perPage, $total);

require __DIR__ . '/includes/header.php';
?>

<?php if ($dbError): ?>
  <div class="mb-6 bg-amber-50 border border-amber-200 rounded-xl p-4 text-sm text-amber-900">
    Eroare DB.
    <details class="mt-2"><summary class="cursor-pointer">Detalii</summary><pre class="mt-2 text-xs"><?= e($dbError) ?></pre></details>
  </div>
<?php endif; ?>

<div x-data="volumetriePage({
       rows: <?= htmlspecialchars(json_encode($products), ENT_QUOTES, 'UTF-8') ?>,
       csrf: '<?= e(csrf_token()) ?>',
       accountId: <?= $filterAccount ?>,
       eligible: <?= $eligibleCount ?>,
       startIndex: <?= $startRow ?: 1 ?>
     })">

  <!-- Header -->
  <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
    <div>
      <h1 class="text-2xl font-bold text-slate-900">Volumetrie</h1>
      <p class="text-sm text-slate-500 mt-0.5">
        Dimensiuni (mm) și greutate (g) pentru produse. Trimise la eMAG prin <code>measurements/save</code>.
        Produsele excluse (EAN sau categorie) nu apar aici.
      </p>
    </div>
  </div>

  <!-- Filtre -->
  <form method="get" data-ajax-filters class="bg-white border border-slate-100 rounded-xl shadow-soft p-4 mb-4">
    <div class="grid grid-cols-1 md:grid-cols-5 gap-3">
      <div>
        <label class="block text-xs font-medium text-slate-700 mb-1">Cont eMAG</label>
        <select name="account" onchange="this.form.requestSubmit()"
          class="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 bg-white">
          <option value="">— Toate conturile —</option>
          <?php foreach ($accounts as $acc): ?>
            <option value="<?= (int)$acc['id'] ?>" <?= $filterAccount === (int)$acc['id'] ? 'selected' : '' ?>>
              <?= e($acc['account_name']) ?>
            </option>
          <?php endforeach; ?>
        </select>
      </div>
      <div class="md:col-span-2">
        <label class="block text-xs font-medium text-slate-700 mb-1">Caută</label>
        <input type="text" name="q" value="<?= e($search) ?>" placeholder="Nume, EAN, PNK, eMAG ID…"
          class="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500">
      </div>
      <div>
        <label class="block text-xs font-medium text-slate-700 mb-1">Volumetrie</label>
        <select name="vol" onchange="this.form.requestSubmit()"
          class="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 bg-white">
          <option value="">Toate</option>
          <option value="complete"   <?= $filterComplete === 'complete'   ? 'selected' : '' ?>>Completă</option>
          <option value="incomplete" <?= $filterComplete === 'incomplete' ? 'selected' : '' ?>>Incompletă</option>
        </select>
      </div>
      <div>
        <label class="block text-xs font-medium text-slate-700 mb-1">Pe pagină</label>
        <select name="per_page" onchange="this.form.requestSubmit()"
          class="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 bg-white">
          <?php foreach ($allowedPer as $pp): ?>
            <option value="<?= $pp ?>" <?= $perPage === $pp ? 'selected' : '' ?>><?= $pp ?></option>
          <?php endforeach; ?>
        </select>
      </div>
    </div>
    <?php if ($search !== '' || $filterComplete !== '' || $filterAccount > 0): ?>
      <div class="mt-3 flex items-center gap-3">
        <button type="submit" class="px-3 py-1.5 text-sm font-medium text-white bg-brand-600 hover:bg-brand-700 rounded-lg transition">Aplică</button>
        <a href="<?= e(url('volumetrie.php')) ?>" class="text-sm text-slate-500 hover:text-slate-700">Resetează filtrele</a>
      </div>
    <?php endif; ?>
  </form>

  <!-- Panou Sync la eMAG -->
  <div class="bg-white border border-slate-100 rounded-xl shadow-soft p-5 mb-4">
    <div class="flex items-center justify-between gap-4 flex-wrap">
      <div class="text-sm">
        <?php if ($filterAccount > 0 && $selectedAccount): ?>
          <div class="font-medium text-slate-800">Trimite volumetria la <span class="text-brand-700"><?= e($selectedAccount['account_name']) ?></span></div>
          <div class="text-slate-500 mt-0.5">
            <strong x-text="eligible"></strong> produse cu volumetrie completă și <code>emag_id</code> sunt gata de trimis.
          </div>
        <?php else: ?>
          <div class="font-medium text-slate-800">Selectează un cont pentru a putea trimite volumetria la eMAG</div>
          <div class="text-slate-500 mt-0.5">Push-ul se face per cont (credențiale eMAG diferite).</div>
        <?php endif; ?>
      </div>
      <button @click="startSync()"
        :disabled="running || !accountId || eligible === 0"
        class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-brand-600 hover:bg-brand-700 rounded-lg shadow-soft transition disabled:opacity-50 disabled:cursor-not-allowed">
        <svg x-show="!running" class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582M20 20v-5h-.581M5.5 9a7.5 7.5 0 0113 -2.5M18.5 15a7.5 7.5 0 01-13 2.5"/></svg>
        <span x-show="running" class="spinner"></span>
        <span x-text="running ? 'Trimit…' : 'Sync la eMAG'"></span>
      </button>
    </div>

    <!-- Progress -->
    <template x-if="running || done">
      <div class="mt-5">
        <div class="flex items-center justify-between text-sm mb-2">
          <div class="font-medium text-slate-700">
            <span x-show="running">Trimitere în progres…</span>
            <span x-show="done && !error" class="text-emerald-700">✓ Trimitere finalizată</span>
            <span x-show="error" class="text-rose-700">✗ Trimitere eșuată</span>
          </div>
          <div class="text-xs text-slate-500"><span x-text="totals.processed"></span> / <span x-text="totals.total"></span></div>
        </div>
        <div class="w-full h-2 bg-slate-100 rounded-full overflow-hidden">
          <div class="h-full bg-gradient-to-r from-brand-500 to-brand-600 transition-all duration-300" :style="`width: ${progressPercent()}%`"></div>
        </div>
        <div class="mt-4 grid grid-cols-3 gap-3">
          <div class="bg-emerald-50 rounded-lg p-3">
            <div class="text-[11px] uppercase tracking-wide text-emerald-700 font-medium">Trimise</div>
            <div class="text-xl font-bold text-emerald-900 mt-0.5" x-text="totals.sent"></div>
          </div>
          <div class="bg-rose-50 rounded-lg p-3">
            <div class="text-[11px] uppercase tracking-wide text-rose-700 font-medium">Erori</div>
            <div class="text-xl font-bold text-rose-900 mt-0.5" x-text="totals.failed"></div>
          </div>
          <div class="bg-slate-50 rounded-lg p-3">
            <div class="text-[11px] uppercase tracking-wide text-slate-600 font-medium">Procesate</div>
            <div class="text-xl font-bold text-slate-900 mt-0.5" x-text="totals.processed"></div>
          </div>
        </div>
        <div class="mt-4">
          <div class="bg-slate-900 text-slate-300 font-mono text-[12px] rounded-lg p-3 max-h-56 overflow-y-auto" x-ref="logBox">
            <template x-for="(line, i) in logLines" :key="i">
              <div class="leading-relaxed" :class="line.type === 'error' ? 'text-rose-400' : (line.type === 'success' ? 'text-emerald-400' : 'text-slate-400')">
                <span class="text-slate-600" x-text="line.time"></span><span x-text="line.text"></span>
              </div>
            </template>
            <template x-if="logLines.length === 0"><div class="text-slate-600 italic">Așteptare…</div></template>
          </div>
        </div>
        <template x-if="done">
          <div class="mt-3 text-sm">
            <a href="" @click.prevent="window.location.reload()" class="text-brand-600 hover:text-brand-700 font-medium">↻ Reîncarcă lista</a>
          </div>
        </template>
      </div>
    </template>
  </div>

  <!-- Bara setare în masă (apare când ai selecții) -->
  <div x-show="selectedIds.length > 0" x-cloak
       class="bg-brand-50 border border-brand-200 rounded-xl shadow-soft p-4 mb-4">
    <div class="flex flex-col lg:flex-row lg:items-end gap-3">
      <div class="text-sm font-medium text-brand-900 whitespace-nowrap">
        <span x-text="selectedIds.length"></span> selectate
      </div>
      <div class="grid grid-cols-2 sm:grid-cols-4 gap-2 flex-1">
        <div>
          <label class="block text-[11px] font-medium text-slate-600 mb-1">Lungime (mm)</label>
          <input type="number" min="0" max="999999" step="0.01" x-model="bulk.length_mm"
            class="w-full px-2 py-1.5 text-sm text-right tabular-nums border border-slate-200 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500">
        </div>
        <div>
          <label class="block text-[11px] font-medium text-slate-600 mb-1">Lățime (mm)</label>
          <input type="number" min="0" max="999999" step="0.01" x-model="bulk.width_mm"
            class="w-full px-2 py-1.5 text-sm text-right tabular-nums border border-slate-200 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500">
        </div>
        <div>
          <label class="block text-[11px] font-medium text-slate-600 mb-1">Înălțime (mm)</label>
          <input type="number" min="0" max="999999" step="0.01" x-model="bulk.height_mm"
            class="w-full px-2 py-1.5 text-sm text-right tabular-nums border border-slate-200 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500">
        </div>
        <div>
          <label class="block text-[11px] font-medium text-slate-600 mb-1">Greutate (g)</label>
          <input type="number" min="0" max="999999" step="0.01" x-model="bulk.weight_g"
            class="w-full px-2 py-1.5 text-sm text-right tabular-nums border border-slate-200 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500">
        </div>
      </div>
      <div class="flex items-center gap-2">
        <button @click="applyBulk()" :disabled="bulkSaving"
          class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-brand-600 hover:bg-brand-700 rounded-lg shadow-soft transition disabled:opacity-50 whitespace-nowrap">
          <span x-show="bulkSaving" class="spinner"></span>
          <span x-text="bulkSaving ? 'Aplic…' : 'Aplică la selectate'"></span>
        </button>
        <button @click="clearSelection()" class="px-3 py-2 text-sm text-slate-600 hover:text-slate-800 whitespace-nowrap">Deselectează</button>
      </div>
    </div>
    <p class="text-[11px] text-slate-500 mt-2">Câmpurile lăsate goale nu se modifică. Se salvează doar local — trimite la eMAG din panoul de sus.</p>
  </div>

  <!-- Tabel -->
  <div class="bg-white border border-slate-100 rounded-xl shadow-soft overflow-hidden">
    <div class="overflow-x-auto">
      <table class="w-full text-sm">
        <thead>
          <tr class="border-b border-slate-100 bg-slate-50/60 text-left text-xs font-medium text-slate-500 uppercase tracking-wide">
            <th class="px-3 py-3 w-10">
              <input type="checkbox" @change="toggleAll($event.target.checked)" :checked="allSelected()"
                class="rounded border-slate-300 text-brand-600 focus:ring-brand-500 cursor-pointer">
            </th>
            <th class="px-2 py-3 w-12 text-right">#</th>
            <th class="px-4 py-3">Produs</th>
            <th class="px-3 py-3 w-24">Lungime<br><span class="normal-case text-[10px] text-slate-400">mm</span></th>
            <th class="px-3 py-3 w-24">Lățime<br><span class="normal-case text-[10px] text-slate-400">mm</span></th>
            <th class="px-3 py-3 w-24">Înălțime<br><span class="normal-case text-[10px] text-slate-400">mm</span></th>
            <th class="px-3 py-3 w-24">Greutate<br><span class="normal-case text-[10px] text-slate-400">g</span></th>
            <th class="px-3 py-3 w-28">Stare</th>
            <th class="px-3 py-3 w-32 text-center">Acțiune</th>
          </tr>
        </thead>
        <tbody class="divide-y divide-slate-50">
          <template x-for="(p, idx) in rows" :key="p.id">
            <tr class="hover:bg-slate-50/50" :class="isSelected(p.id) ? 'bg-brand-50/40' : ''">
              <td class="px-3 py-2.5">
                <input type="checkbox" :value="p.id" :checked="isSelected(p.id)" @change="toggleOne(p.id, $event.target.checked)"
                  class="rounded border-slate-300 text-brand-600 focus:ring-brand-500 cursor-pointer">
              </td>
              <td class="px-2 py-2.5 text-right text-xs text-slate-400 tabular-nums" x-text="startIndex + idx"></td>
              <td class="px-4 py-2.5">
                <div class="font-medium text-slate-800 line-clamp-2" x-text="p.product_name"></div>
                <div class="text-[11px] text-slate-400 font-mono mt-0.5 flex flex-wrap gap-x-3">
                  <span x-show="p.ean">EAN: <span x-text="p.ean"></span></span>
                  <span x-show="p.account_name" x-text="p.account_name"></span>
                  <span x-show="!p.emag_id" class="text-amber-600">fără emag_id</span>
                </div>
              </td>
              <template x-for="field in ['length_mm','width_mm','height_mm','weight_g']" :key="field">
                <td class="px-3 py-2.5">
                  <input type="number" min="0" max="999999" step="0.01"
                    x-model="p[field]"
                    @focus="snapshot(p)"
                    @change="saveRow(p)"
                    @keydown.enter.prevent="$event.target.blur()"
                    class="w-20 px-2 py-1.5 text-sm text-right tabular-nums border border-slate-200 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500">
                </td>
              </template>
              <td class="px-3 py-2.5">
                <template x-if="rowComplete(p)">
                  <span x-show="p.volumetrie_synced_at" class="inline-flex items-center gap-1 text-xs text-emerald-700">
                    <span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span> sincronizat
                  </span>
                </template>
                <template x-if="rowComplete(p)">
                  <span x-show="!p.volumetrie_synced_at" class="inline-flex items-center gap-1 text-xs text-sky-700">
                    <span class="w-1.5 h-1.5 rounded-full bg-sky-500"></span> de trimis
                  </span>
                </template>
                <template x-if="!rowComplete(p)">
                  <span class="inline-flex items-center gap-1 text-xs text-slate-400">
                    <span class="w-1.5 h-1.5 rounded-full bg-slate-300"></span> incompletă
                  </span>
                </template>
              </td>
              <td class="px-3 py-2.5 text-center">
                <template x-if="rowComplete(p) && p.emag_id">
                  <button @click="sendOne(p)" :disabled="isSending(p.id)"
                    class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-white bg-brand-600 hover:bg-brand-700 rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed"
                    :title="p.volumetrie_synced_at ? 'Retrimite la eMAG' : 'Trimite la eMAG'">
                    <span x-show="isSending(p.id)" class="spinner"></span>
                    <svg x-show="!isSending(p.id)" class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14M12 5l7 7-7 7"/></svg>
                    <span x-text="isSending(p.id) ? 'Trimit…' : (p.volumetrie_synced_at ? 'Retrimite' : 'Trimite')"></span>
                  </button>
                </template>
                <template x-if="!(rowComplete(p) && p.emag_id)">
                  <span class="text-xs text-slate-300">—</span>
                </template>
              </td>
            </tr>
          </template>
          <template x-if="rows.length === 0">
            <tr><td colspan="9" class="px-4 py-12 text-center text-sm text-slate-400">Niciun produs.</td></tr>
          </template>
        </tbody>
      </table>
    </div>
  </div>

  <!-- Paginare -->
  <?php if ($totalPages > 1): ?>
    <div class="mt-4 flex items-center justify-between text-sm">
      <div class="text-slate-500">Afișez <strong><?= $startRow ?>–<?= $endRow ?></strong> din <strong><?= number_format($total, 0, ',', '.') ?></strong></div>
      <div class="flex items-center gap-1">
        <?php if ($page > 1): ?>
          <a href="<?= e(vol_url(['page' => $page - 1])) ?>" class="px-3 py-1.5 border border-slate-200 rounded-lg hover:bg-slate-50">‹ Anterior</a>
        <?php endif; ?>
        <span class="px-3 py-1.5 text-slate-500">Pagina <?= $page ?> / <?= $totalPages ?></span>
        <?php if ($page < $totalPages): ?>
          <a href="<?= e(vol_url(['page' => $page + 1])) ?>" class="px-3 py-1.5 border border-slate-200 rounded-lg hover:bg-slate-50">Următor ›</a>
        <?php endif; ?>
      </div>
    </div>
  <?php endif; ?>

</div>

<script>
function volumetriePage(cfg) {
  return {
    rows: cfg.rows,
    csrf: cfg.csrf,
    accountId: cfg.accountId,
    eligible: cfg.eligible,
    startIndex: cfg.startIndex,
    _snap: {},

    // --- Selecție multiplă ---
    selectedIds: [],
    bulk: { length_mm: '', width_mm: '', height_mm: '', weight_g: '' },
    bulkSaving: false,

    isSelected(id) { return this.selectedIds.includes(id); },
    toggleOne(id, on) {
      if (on) { if (!this.isSelected(id)) this.selectedIds.push(id); }
      else    { this.selectedIds = this.selectedIds.filter(x => x !== id); }
    },
    allSelected() { return this.rows.length > 0 && this.selectedIds.length === this.rows.length; },
    toggleAll(on) { this.selectedIds = on ? this.rows.map(p => p.id) : []; },
    clearSelection() {
      this.selectedIds = [];
      this.bulk = { length_mm: '', width_mm: '', height_mm: '', weight_g: '' };
    },

    // --- Trimitere individuală la eMAG ---
    sendingIds: [],
    isSending(id) { return this.sendingIds.includes(id); },
    async sendOne(p) {
      if (this.isSending(p.id)) return;
      this.sendingIds.push(p.id);
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('id', p.id);
        const r = await fetch('<?= url('api/volumetrie-send-one.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error || 'Eroare');
        p.volumetrie_synced_at = data.volumetrie_synced_at;
      } catch (e) {
        alert('Eroare trimitere „' + (p.product_name || '').slice(0, 60) + '": ' + e.message);
      } finally {
        this.sendingIds = this.sendingIds.filter(x => x !== p.id);
      }
    },

    async applyBulk() {
      if (this.selectedIds.length === 0 || this.bulkSaving) return;
      const hasValue = ['length_mm','width_mm','height_mm','weight_g'].some(k => String(this.bulk[k]).trim() !== '');
      if (!hasValue) { alert('Completează cel puțin un câmp de volumetrie.'); return; }
      this.bulkSaving = true;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        this.selectedIds.forEach(id => fd.append('ids[]', id));
        ['length_mm','width_mm','height_mm','weight_g'].forEach(k => fd.append(k, this.bulk[k] ?? ''));
        const r = await fetch('<?= url('api/save-volumetrie-bulk.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error || 'Eroare');
        // Sincronizează rândurile din tabel cu valorile salvate
        const byId = {};
        (data.products || []).forEach(p => byId[p.id] = p);
        this.rows.forEach(p => { if (byId[p.id]) Object.assign(p, byId[p.id]); });
        this.bulk = { length_mm: '', width_mm: '', height_mm: '', weight_g: '' };
      } catch (e) {
        alert('Eroare salvare în masă: ' + e.message);
      } finally {
        this.bulkSaving = false;
      }
    },

    running: false,
    done: false,
    error: false,
    totals: { sent: 0, failed: 0, processed: 0, total: 0 },
    logLines: [],

    rowComplete(p) {
      return ['length_mm','width_mm','height_mm','weight_g'].every(
        k => p[k] !== null && p[k] !== '' && p[k] !== undefined
      );
    },

    snapshot(p) {
      this._snap[p.id] = { length_mm: p.length_mm, width_mm: p.width_mm, height_mm: p.height_mm, weight_g: p.weight_g };
    },

    async saveRow(p) {
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('id', p.id);
        ['length_mm','width_mm','height_mm','weight_g'].forEach(k => fd.append(k, p[k] ?? ''));
        const r = await fetch('<?= url('api/save-volumetrie.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error || 'Eroare');
        Object.assign(p, data.product); // include volumetrie_synced_at = null
      } catch (e) {
        // rollback la valorile dinainte de editare
        const s = this._snap[p.id];
        if (s) Object.assign(p, s);
        alert('Eroare salvare: ' + e.message);
      }
    },

    progressPercent() {
      if (this.done) return 100;
      if (this.totals.total > 0) return Math.min(99, Math.round((this.totals.processed / this.totals.total) * 100));
      return 5;
    },

    log(text, type = 'info') {
      const t = new Date().toLocaleTimeString('ro-RO');
      this.logLines.push({ time: `[${t}] `, text, type });
      this.$nextTick(() => { if (this.$refs.logBox) this.$refs.logBox.scrollTop = this.$refs.logBox.scrollHeight; });
    },

    async startSync() {
      if (!this.accountId || this.eligible === 0 || this.running) return;
      this.running = true; this.done = false; this.error = false;
      this.totals = { sent: 0, failed: 0, processed: 0, total: this.eligible };
      this.logLines = [];
      this.log(`Start trimitere volumetrie (${this.eligible} produse)`, 'info');

      let offset = 0;
      let safety = 1000;
      try {
        while (safety-- > 0) {
          const fd = new FormData();
          fd.append('csrf_token', this.csrf);
          fd.append('account_id', this.accountId);
          fd.append('offset', offset);
          const r = await fetch('<?= url('api/volumetrie-sync.php') ?>', { method: 'POST', body: fd });
          const data = await r.json();
          if (!data.ok) throw new Error(data.error || 'Eroare necunoscută');

          this.totals.total      = data.total;
          this.totals.sent      += data.stats.sent;
          this.totals.failed    += data.stats.failed;
          this.totals.processed += data.processed;
          this.log(`  ✓ lot: ${data.processed} procesate · ${data.stats.sent} trimise · ${data.stats.failed} erori`, 'success');
          (data.errors_log || []).forEach(m => this.log(`  ⚠ ${m}`, 'error'));

          if (!data.has_more || data.processed === 0) break;
          offset = data.next_offset;
        }
        this.log(`✓ FINALIZAT: ${this.totals.sent} trimise, ${this.totals.failed} erori`, 'success');
        this.done = true;
        // marchează rândurile vizibile complete ca sincronizate (aproximativ)
      } catch (e) {
        this.log(`✗ EROARE: ${e.message}`, 'error');
        this.error = true; this.done = true;
      } finally {
        this.running = false;
      }
    }
  };
}
</script>

<?php require __DIR__ . '/includes/footer.php'; ?>
