<?php
/**
 * Validare documentație — produsele aflate în validare pe eMAG.
 *
 * După ce editezi documentația unui produs deja aprobat (ex. descrierea), eMAG
 * îl trece în `validation_status` = 11 („Actualizare în validare"): produsul
 * rămâne vandabil, dar modificarea așteaptă validarea. Dacă update-ul e refuzat,
 * ajunge în 12 („Actualizare respinsă").
 *
 * Pagina citește produsele direct de pe eMAG folosind filtrul nativ
 * `validation_status` din product_offer/read (vezi api/validation-check.php), deci
 * nu parcurge tot catalogul. Rezultatul e și salvat în products, ca să rămână
 * vizibil la reîncărcarea paginii.
 */
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/emag-api.php';

$pageTitle  = 'Validare documentație';
$breadcrumb = [['label' => 'Validare documentație']];

$accounts        = active_accounts_list();
$activeAccountId = active_account_id();

// Statusurile oferite spre verificare. 9 („Documentație aprobată") lipsește
// intenționat: ar întoarce practic tot catalogul, fără valoare informativă aici.
$checkable = [
    11 => ['primary' => true,  'tone' => 'amber'],   // Actualizare în validare
    12 => ['primary' => true,  'tone' => 'rose'],    // Actualizare respinsă
    4  => ['primary' => false, 'tone' => 'sky'],     // Documentație nouă în validare
    1  => ['primary' => false, 'tone' => 'sky'],     // În validare MKTP
    2  => ['primary' => false, 'tone' => 'sky'],     // În așteptare validare brand
    8  => ['primary' => false, 'tone' => 'rose'],    // Documentație respinsă
    5  => ['primary' => false, 'tone' => 'rose'],    // Brand respins
    6  => ['primary' => false, 'tone' => 'rose'],    // EAN respins
    10 => ['primary' => false, 'tone' => 'slate'],   // Blocat
    3  => ['primary' => false, 'tone' => 'slate'],   // Așteaptă aprobare EAN
];

// Snapshot-ul salvat la ultima verificare (ca să nu fie pagina goală la load).
// Excludem statusul 9 („Documentație aprobată"): sync-ul general îl scrie pe
// aproape tot catalogul, iar aici ne interesează doar ce NU e încă aprobat.
$dbError  = null;
$snapshot = [];
try {
    $where  = "p.emag_validation_status IS NOT NULL AND p.emag_validation_status <> 9";
    $params = [];
    if ($activeAccountId > 0) {
        $where .= " AND p.emag_account_id = ?";
        $params[] = $activeAccountId;
    }
    $snapshot = db_select(
        "SELECT p.id                     AS product_id,
                p.emag_account_id        AS account_id,
                a.account_name           AS account_name,
                p.pnk, p.ean,
                p.product_name           AS name,
                p.emag_part_number       AS part_number,
                p.emag_validation_status AS status,
                p.emag_validation_desc   AS status_desc,
                p.emag_validation_all    AS all_statuses,
                p.emag_validation_errors AS errors,
                p.emag_offer_status      AS offer_status,
                p.validation_checked_at  AS checked_at
           FROM products p
           LEFT JOIN emag_accounts a ON a.id = p.emag_account_id
          WHERE $where
          ORDER BY CASE p.emag_validation_status WHEN 11 THEN 0 WHEN 12 THEN 1 ELSE 2 END,
                   p.product_name COLLATE NOCASE ASC",
        $params
    );
    foreach ($snapshot as &$r) {
        $r['status']       = (int)$r['status'];
        $r['status_label'] = EmagAPI::validationLabel((int)$r['status']);
        $r['in_db']        = 1;
    }
    unset($r);
} catch (Throwable $ex) {
    $dbError = $ex->getMessage();
}

$lastChecked = null;
foreach ($snapshot as $r) {
    if (!empty($r['checked_at']) && ($lastChecked === null || $r['checked_at'] > $lastChecked)) {
        $lastChecked = $r['checked_at'];
    }
}

// Etichetele + tonurile trimise în JS (pentru badge-uri)
$labels = [];
foreach (EmagAPI::VALIDATION_STATUSES as $v => $meta) {
    $labels[$v] = [
        'label'     => $meta['label'],
        'available' => $meta['available'] ? 1 : 0,
        'tone'      => $checkable[$v]['tone'] ?? 'slate',
    ];
}

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="validationPage(
       <?= htmlspecialchars(json_encode($snapshot), ENT_QUOTES, 'UTF-8') ?>,
       <?= htmlspecialchars(json_encode(array_map(fn($a) => ['id' => (int)$a['id'], 'account_name' => $a['account_name']], $accounts)), ENT_QUOTES, 'UTF-8') ?>,
       <?= htmlspecialchars(json_encode($labels), ENT_QUOTES, 'UTF-8') ?>,
       <?= (int)$activeAccountId ?>
     )">

  <!-- Header -->
  <div class="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4 mb-6">
    <div>
      <h1 class="text-2xl font-bold text-slate-900">Validare documentație</h1>
      <p class="text-sm text-slate-500 mt-0.5 max-w-3xl">
        Extrage de pe eMAG produsele al căror status de documentație este
        <strong>Actualizare în validare</strong> — adică cele la care ai editat descrierea (sau alt câmp
        de documentație) și eMAG încă nu a validat modificarea. Se citește direct prin filtrul
        <code>validation_status</code> din <code>product_offer/read</code>, nu din baza locală.
      </p>
      <?php if ($lastChecked): ?>
        <p class="text-xs text-slate-400 mt-1">Ultima verificare: <?= e($lastChecked) ?></p>
      <?php endif; ?>
    </div>
  </div>

  <?php if (!$accounts): ?>
    <div class="bg-white border border-slate-100 rounded-xl shadow-soft p-12 text-center">
      <h2 class="font-semibold text-slate-900 mb-1">Niciun cont eMAG activ</h2>
      <p class="text-sm text-slate-500">Adaugă un cont în
        <a href="<?= url('settings.php') ?>" class="text-brand-600 hover:underline">Setări</a>.</p>
    </div>
  <?php else: ?>

  <!-- Panou verificare -->
  <div class="bg-white border border-slate-100 rounded-xl shadow-soft p-5 mb-5">
    <div class="grid md:grid-cols-3 gap-5">

      <!-- Cont -->
      <div>
        <label class="block text-xs font-medium text-slate-700 mb-1.5">Cont eMAG</label>
        <select x-model="accountSel" :disabled="running"
          class="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-200 focus:border-brand-400 disabled:opacity-50">
          <option value="0">Toate conturile active (<?= count($accounts) ?>)</option>
          <?php foreach ($accounts as $a): ?>
            <option value="<?= (int)$a['id'] ?>"><?= e($a['account_name']) ?></option>
          <?php endforeach; ?>
        </select>
      </div>

      <!-- Statusuri -->
      <div class="md:col-span-2">
        <label class="block text-xs font-medium text-slate-700 mb-1.5">Statusuri de extras</label>
        <div class="flex flex-wrap gap-2">
          <?php foreach ($checkable as $v => $meta): if (!$meta['primary']) continue; ?>
            <label class="inline-flex items-center gap-2 px-3 py-1.5 text-sm border rounded-lg cursor-pointer transition"
                   :class="statuses.includes(<?= $v ?>) ? 'bg-slate-900 text-white border-slate-900' : 'bg-white text-slate-600 border-slate-200 hover:bg-slate-50'">
              <input type="checkbox" value="<?= $v ?>" x-model.number="statuses" :disabled="running" class="hidden">
              <span class="font-medium"><?= e(EmagAPI::validationLabel($v)) ?></span>
              <span class="text-[11px] opacity-60">#<?= $v ?></span>
            </label>
          <?php endforeach; ?>
        </div>

        <details class="mt-2">
          <summary class="text-xs text-slate-500 hover:text-slate-700 cursor-pointer">Alte statusuri</summary>
          <div class="flex flex-wrap gap-1.5 mt-2">
            <?php foreach ($checkable as $v => $meta): if ($meta['primary']) continue; ?>
              <label class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs border rounded-lg cursor-pointer transition"
                     :class="statuses.includes(<?= $v ?>) ? 'bg-slate-700 text-white border-slate-700' : 'bg-white text-slate-500 border-slate-200 hover:bg-slate-50'">
                <input type="checkbox" value="<?= $v ?>" x-model.number="statuses" :disabled="running" class="hidden">
                <span><?= e(EmagAPI::validationLabel($v)) ?></span>
              </label>
            <?php endforeach; ?>
          </div>
          <p class="text-[11px] text-slate-400 mt-2">
            „Documentație aprobată” (9) nu e ofertă de verificare aici — ar întoarce întreg catalogul.
          </p>
        </details>
      </div>
    </div>

    <div class="flex items-center gap-3 mt-5 pt-4 border-t border-slate-100 flex-wrap">
      <button @click="check()" :disabled="running || statuses.length === 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">
        <span x-show="running" class="spinner"></span>
        <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-text="running ? 'Se verifică…' : 'Verifică pe eMAG'"></span>
      </button>
      <button @click="exportCsv()" :disabled="rows.length === 0"
        class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-slate-600 bg-white border border-slate-200 hover:bg-slate-50 rounded-lg transition disabled:opacity-50">
        <svg 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 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M7 10l5 5 5-5M12 15V3"/></svg>
        Export CSV
      </button>
      <button @click="copyList('pnk')" :disabled="visibleRows().length === 0"
        class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-slate-600 bg-white border border-slate-200 hover:bg-slate-50 rounded-lg transition disabled:opacity-50">
        <svg 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="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg>
        <span x-text="copied === 'pnk' ? 'Copiat ✓' : 'Copiază PNK-urile (' + copyCount('pnk') + ')'"></span>
      </button>
      <button @click="copyList('ean')" :disabled="visibleRows().length === 0"
        class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-slate-600 bg-white border border-slate-200 hover:bg-slate-50 rounded-lg transition disabled:opacity-50">
        <svg 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="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg>
        <span x-text="copied === 'ean' ? 'Copiat ✓' : 'Copiază EAN-urile (' + copyCount('ean') + ')'"></span>
      </button>
      <span class="text-xs text-slate-400" x-show="!running && lastRunAt" x-cloak>
        verificat la <span x-text="lastRunAt"></span>
      </span>
    </div>

    <!-- Progres -->
    <template x-if="running || logLines.length">
      <div class="mt-4 pt-4 border-t border-slate-100">
        <div class="bg-slate-900 text-slate-300 font-mono text-[12px] rounded-lg p-3 max-h-48 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>
        </div>
      </div>
    </template>
  </div>

  <!-- Sumar pe statusuri -->
  <div class="flex items-center gap-1.5 mb-4 flex-wrap">
    <button @click="filter = 0"
      class="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium rounded-lg transition"
      :class="filter === 0 ? 'bg-slate-900 text-white' : 'bg-white text-slate-600 border border-slate-200 hover:bg-slate-50'">
      Toate
      <span class="text-xs px-1.5 py-0.5 rounded-full"
        :class="filter === 0 ? 'bg-white/20' : 'bg-slate-100 text-slate-500'" x-text="rows.length"></span>
    </button>
    <template x-for="s in presentStatuses()" :key="s">
      <button @click="filter = s"
        class="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium rounded-lg transition"
        :class="filter === s ? 'bg-slate-900 text-white' : 'bg-white text-slate-600 border border-slate-200 hover:bg-slate-50'">
        <span x-text="labelOf(s)"></span>
        <span class="text-xs px-1.5 py-0.5 rounded-full"
          :class="filter === s ? 'bg-white/20' : 'bg-slate-100 text-slate-500'" x-text="countOf(s)"></span>
      </button>
    </template>
    <div class="flex-1"></div>
    <input type="search" x-model="search" placeholder="Caută nume / PNK / EAN…"
      class="px-3 py-1.5 text-sm border border-slate-200 rounded-lg w-64 focus:outline-none focus:ring-2 focus:ring-brand-200 focus:border-brand-400">
  </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="text-left text-[11px] font-medium text-slate-400 uppercase tracking-wide border-b border-slate-100">
            <th class="px-4 py-3">PNK</th>
            <th class="px-3 py-3">EAN</th>
            <th class="px-3 py-3">Produs</th>
            <th class="px-3 py-3">Cont</th>
            <th class="px-4 py-3">Status validare</th>
          </tr>
        </thead>
        <tbody class="divide-y divide-slate-50">
          <template x-for="(row, idx) in visibleRows()" :key="idx">
            <tr class="hover:bg-slate-50/60">
              <!-- PNK -->
              <td class="px-4 py-3 align-top font-mono whitespace-nowrap">
                <template x-if="row.pnk">
                  <a :href="'https://www.emag.ro/-/pd/' + row.pnk" target="_blank" rel="noopener"
                     class="text-brand-600 hover:underline" x-text="row.pnk"></a>
                </template>
                <span x-show="!row.pnk" class="text-slate-300">—</span>
              </td>
              <!-- EAN -->
              <td class="px-3 py-3 align-top font-mono text-slate-700 whitespace-nowrap">
                <span x-text="row.ean || '—'" :class="!row.ean ? 'text-slate-300' : ''"></span>
              </td>
              <!-- Produs -->
              <td class="px-3 py-3 align-top">
                <div class="text-slate-800 max-w-[420px] break-words" x-text="row.name || '—'"></div>
                <div class="text-[11px] text-slate-400 mt-0.5 flex items-center gap-2 flex-wrap">
                  <span x-show="row.part_number" class="font-mono">cod: <span x-text="row.part_number"></span></span>
                  <span x-show="row.offer_status === 0" class="text-rose-500">ofertă inactivă</span>
                  <span x-show="row.offer_status === 2" class="text-rose-500">EOL</span>
                  <span x-show="!row.in_db" class="text-amber-600">nesincronizat local</span>
                </div>
                <template x-if="row.errors">
                  <details class="mt-1">
                    <summary class="text-[11px] text-rose-500 cursor-pointer">feedback eMAG</summary>
                    <pre class="mt-1 text-[11px] text-slate-600 bg-slate-50 rounded p-2 whitespace-pre-wrap break-words max-w-[420px]" x-text="row.errors"></pre>
                  </details>
                </template>
              </td>
              <!-- Cont -->
              <td class="px-3 py-3 align-top text-slate-600 whitespace-nowrap" x-text="row.account_name || '—'"></td>
              <!-- Status -->
              <td class="px-4 py-3 align-top whitespace-nowrap">
                <span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-full"
                      :class="badgeClass(row.status)">
                  <span class="w-1.5 h-1.5 rounded-full bg-current opacity-70"></span>
                  <span x-text="row.status_label || ('Status ' + row.status)"></span>
                </span>
                <!-- Un produs poate avea mai multe statusuri simultan (ex: conflict EAN + update în validare) -->
                <div class="flex flex-wrap gap-1 mt-1">
                  <template x-for="s in otherStatuses(row)" :key="s">
                    <span class="inline-flex items-center px-2 py-0.5 text-[11px] rounded-full"
                          :class="badgeClass(s)" x-text="'+ ' + labelOf(s)"></span>
                  </template>
                </div>
                <div class="text-[11px] text-slate-400 mt-1" x-show="row.status_desc" x-text="row.status_desc"></div>
              </td>
            </tr>
          </template>
        </tbody>
      </table>
    </div>
    <div x-show="visibleRows().length === 0" x-cloak class="p-10 text-center text-sm text-slate-500">
      <template x-if="rows.length === 0">
        <span>Niciun produs în validare. Apasă <strong>Verifică pe eMAG</strong> ca să extragi lista curentă.</span>
      </template>
      <template x-if="rows.length > 0">
        <span>Niciun rezultat pentru filtrul curent.</span>
      </template>
    </div>
  </div>

  <?php endif; ?>
</div>

<script>
function validationPage(snapshot, accounts, labels, activeAccountId) {
  return {
    rows: snapshot || [],
    accounts: accounts || [],
    labels: labels || {},
    accountSel: String(activeAccountId || 0),
    statuses: [<?= EmagAPI::VALIDATION_UPDATE_PENDING ?>],
    csrf: '<?= e(csrf_token()) ?>',

    filter: 0,
    search: '',
    copied: '',
    running: false,
    lastRunAt: '',
    logLines: [],

    labelOf(s)  { return (this.labels[s] && this.labels[s].label) || ('Status ' + s); },
    countOf(s)  { return this.rows.filter(r => Number(r.status) === Number(s)).length; },
    presentStatuses() {
      return [...new Set(this.rows.map(r => Number(r.status)))].sort((a, b) => a - b);
    },
    // Statusurile secundare (un produs poate avea mai multe deodată, ex: 3 + 11)
    otherStatuses(row) {
      return String(row.all_statuses || '')
        .split(',').map(s => Number(s.trim()))
        .filter(s => !isNaN(s) && s !== Number(row.status));
    },
    badgeClass(s) {
      const tone = (this.labels[s] && this.labels[s].tone) || 'slate';
      return {
        amber: 'bg-amber-50 text-amber-700',
        rose:  'bg-rose-50 text-rose-700',
        sky:   'bg-sky-50 text-sky-700',
        slate: 'bg-slate-100 text-slate-600',
      }[tone] || 'bg-slate-100 text-slate-600';
    },

    visibleRows() {
      const q = this.search.trim().toLowerCase();
      return this.rows.filter(r => {
        if (this.filter && Number(r.status) !== Number(this.filter)) return false;
        if (!q) return true;
        const blob = [r.name, r.pnk, r.ean, r.part_number, r.account_name]
          .filter(Boolean).join(' ').toLowerCase();
        return blob.includes(q);
      });
    },

    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; });
    },

    targetAccounts() {
      const id = Number(this.accountSel);
      return id > 0 ? this.accounts.filter(a => a.id === id) : this.accounts;
    },

    async post(body) {
      const fd = new FormData();
      fd.append('csrf_token', this.csrf);
      Object.entries(body).forEach(([k, v]) => fd.append(k, v));
      const r = await fetch('<?= url('api/validation-check.php') ?>', { method: 'POST', body: fd });
      const data = await r.json();
      if (!data.ok) throw new Error(data.error || 'Eroare necunoscută');
      return data;
    },

    async check() {
      if (this.running || this.statuses.length === 0) return;
      this.running = true;
      this.logLines = [];
      const collected = [];
      const accs = this.targetAccounts();
      this.log(`Start verificare — ${accs.length} cont(uri), statusuri: ${this.statuses.map(s => this.labelOf(s)).join(', ')}`);

      try {
        for (const acc of accs) {
          // Curăță snapshot-ul vechi doar pentru statusurile re-verificate:
          // produsele aprobate între timp nu mai apar în răspunsul filtrat.
          await this.post({ action: 'reset', account_id: acc.id, statuses: this.statuses.join(',') });

          for (const status of this.statuses) {
            let page = 1, safety = 100, found = 0;
            while (safety-- > 0) {
              const data = await this.post({ action: 'page', account_id: acc.id, status, page });
              collected.push(...data.rows);
              found += data.rows.length;
              if (!data.has_more || data.processed === 0) break;
              page = data.next_page;
            }
            this.log(`  ${acc.account_name} · ${this.labelOf(status)}: ${found} produse`,
                     found > 0 ? 'success' : 'info');
          }
        }

        // Rândurile proaspete le înlocuiesc pe cele vechi. Păstrăm din lista veche
        // doar ce NU a fost re-verificat acum: alt cont (dacă am verificat unul singur)
        // sau un status pe care nu l-am bifat (ex: 8, știut dintr-un sync anterior).
        const id  = Number(this.accountSel);
        const key = r => [r.account_id, r.pnk || r.ean || r.emag_id || r.product_id].join('|');
        const fresh = new Set(collected.map(key));
        const keep = this.rows.filter(r => {
          if (fresh.has(key(r))) return false;                          // înlocuit de rândul nou
          if (id > 0 && Number(r.account_id) !== id) return true;       // cont neverificat
          return !this.statuses.includes(Number(r.status));             // status neverificat
        });

        const rank = s => (Number(s) === 11 ? 0 : Number(s) === 12 ? 1 : 2);
        this.rows = [...collected, ...keep].sort((a, b) =>
          rank(a.status) - rank(b.status)
          || String(a.name || '').localeCompare(String(b.name || ''), 'ro'));

        this.lastRunAt = new Date().toLocaleTimeString('ro-RO');
        this.log(`✓ Gata: ${collected.length} produse în validare.`, 'success');
      } catch (e) {
        this.log(`✗ EROARE: ${e.message}`, 'error');
      } finally {
        this.running = false;
      }
    },

    exportCsv() {
      const rows = this.visibleRows();
      if (!rows.length) return;
      const esc = v => '"' + String(v ?? '').replace(/"/g, '""') + '"';
      const lines = [['PNK', 'EAN', 'Produs', 'Cod produs', 'Cont', 'Status', 'Cod status'].map(esc).join(',')];
      rows.forEach(r => lines.push([
        r.pnk, r.ean, r.name, r.part_number, r.account_name,
        r.status_label || this.labelOf(r.status), r.status
      ].map(esc).join(',')));
      const blob = new Blob(['﻿' + lines.join('\r\n')], { type: 'text/csv;charset=utf-8;' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = 'validare-emag-' + new Date().toISOString().slice(0, 10) + '.csv';
      a.click();
      URL.revokeObjectURL(a.href);
    },

    // Valorile unice (PNK sau EAN) din rândurile vizibile — adică din filtrul curent.
    copyValues(field) {
      return [...new Set(this.visibleRows().map(r => r[field]).filter(Boolean))];
    },
    copyCount(field) { return this.copyValues(field).length; },

    async copyList(field) {
      const vals = this.copyValues(field);
      if (!vals.length) return;
      // separate prin virgulă, gata de lipit într-un filtru / căutare
      await navigator.clipboard.writeText(vals.join(','));
      this.copied = field;
      setTimeout(() => { this.copied = ''; }, 1500);
    },
  };
}
</script>

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