<?php
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/template-engine.php';

$sessionId = (int)($_GET['id'] ?? 0);
if ($sessionId <= 0) {
    flash_set('error', 'ID sesiune invalid.');
    header('Location: ' . url('title-sessions.php'));
    exit;
}

$session = null;
$items = [];
$dbError = null;
try {
    $rows = db_select(
        "SELECT s.*,
                (SELECT COUNT(*) FROM title_session_items WHERE session_id = s.id) AS items_count,
                (SELECT COUNT(*) FROM title_session_items WHERE session_id = s.id AND sent_status = 'success') AS success_count,
                (SELECT COUNT(*) FROM title_session_items WHERE session_id = s.id AND sent_status = 'failed')  AS failed_count,
                (SELECT COUNT(*) FROM title_session_items WHERE session_id = s.id AND sent_status = 'pending') AS pending_count
         FROM title_sessions s WHERE id = ?",
        [$sessionId]
    );
    if (!$rows) {
        flash_set('error', 'Sesiunea nu există.');
        header('Location: ' . url('title-sessions.php'));
        exit;
    }
    $session = $rows[0];

    $joinSql = template_join_sql();
    $selSql  = template_select_sql();
    $items = db_select(
        "SELECT i.*,
                p.product_name AS current_product_name,
                p.custom_name  AS current_custom_name,
                $selSql
         FROM title_session_items i
         LEFT JOIN products p ON p.id = i.product_id
         $joinSql
         WHERE i.session_id = ?
         ORDER BY i.id ASC",
        [$sessionId]
    );
    $templatesList = db_select(
        "SELECT id, name, template FROM name_templates ORDER BY name COLLATE NOCASE"
    );
} catch (Throwable $ex) {
    $dbError = $ex->getMessage();
    $templatesList = [];
}
$placeholders = template_placeholders();

$pageTitle  = $session['name'] ?? 'Sesiune';
$breadcrumb = [
    ['label' => 'Sesiuni titluri', 'url' => url('title-sessions.php')],
    ['label' => $pageTitle],
];

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: <pre class="mt-2 text-xs"><?= e($dbError) ?></pre>
  </div>
<?php else: ?>

<div x-data="sessionDetail({
  session: <?= htmlspecialchars(json_encode($session), ENT_QUOTES, 'UTF-8') ?>,
  items: <?= htmlspecialchars(json_encode($items), ENT_QUOTES, 'UTF-8') ?>,
  templatesList: <?= htmlspecialchars(json_encode($templatesList), ENT_QUOTES, 'UTF-8') ?>,
  csrf: '<?= e(csrf_token()) ?>'
})">

  <!-- Header -->
  <div class="flex items-start justify-between mb-4 gap-4">
    <div class="min-w-0">
      <h1 class="text-2xl font-bold text-slate-900 break-words" x-text="session.name"></h1>
      <p class="text-sm text-slate-500 mt-0.5" x-show="session.description" x-text="session.description"></p>
      <div class="mt-2 flex items-center gap-2 flex-wrap text-xs">
        <span class="inline-flex items-center gap-1 text-[10px] uppercase tracking-wide font-semibold px-2 py-0.5 rounded-full"
              :class="statusBadgeClass(session.status)" x-text="session.status"></span>
        <span class="text-slate-500">·</span>
        <span class="text-slate-600"><strong x-text="items.length"></strong> itemi</span>
        <span x-show="successCount() > 0" class="text-emerald-700">· ✓ <span x-text="successCount()"></span> trimis</span>
        <span x-show="failedCount() > 0" class="text-rose-700">· ✗ <span x-text="failedCount()"></span> eroare</span>
        <span x-show="pendingCount() > 0" class="text-amber-700">· ⏳ <span x-text="pendingCount()"></span> de trimis</span>
      </div>
    </div>
    <div class="flex items-center gap-2 flex-shrink-0 flex-wrap">
      <a href="<?= url('title-sessions.php') ?>" class="px-3 py-2 text-sm text-slate-600 hover:bg-slate-100 rounded-lg transition">← Înapoi</a>
      <button @click="revertAllLocal()" :disabled="items.length === 0 || revertBusy || sending"
        class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-100 rounded-lg transition disabled:opacity-30 disabled:cursor-not-allowed"
        title="Doar local: restaurează titlurile vechi în DB, fără push la eMAG">
        <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="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"/></svg>
        <span x-text="revertBusy ? 'Revert...' : 'Revert (local)'"></span>
      </button>
      <button @click="revertAll()" :disabled="items.length === 0 || revertBusy || sending"
        class="inline-flex items-center gap-2 px-3.5 py-2 text-sm font-medium text-amber-700 bg-amber-50 hover:bg-amber-100 rounded-lg transition disabled:opacity-30 disabled:cursor-not-allowed"
        title="Restaurează titlurile vechi ȘI trimite rollback la eMAG pentru produsele cu success">
        <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="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"/></svg>
        <span x-text="revertBusy ? 'Revert + sync...' : 'Revert + sync eMAG'"></span>
      </button>
      <button @click="openApplyTemplate()" :disabled="editableCount() === 0"
        class="inline-flex items-center gap-2 px-3.5 py-2 text-sm font-medium text-brand-700 bg-brand-50 hover:bg-brand-100 rounded-lg transition disabled:opacity-30 disabled:cursor-not-allowed"
        title="Generează titluri noi din șablon">
        <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="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/></svg>
        Aplică șablon
      </button>
      <button @click="confirmSend()" :disabled="sending || pendingCount() === 0"
        class="inline-flex items-center gap-2 px-3.5 py-2 text-sm font-medium text-white bg-emerald-600 hover:bg-emerald-700 rounded-lg shadow-soft transition disabled:opacity-30 disabled:cursor-not-allowed">
        <svg x-show="!sending" 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="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/></svg>
        <span x-show="sending" class="spinner"></span>
        <span x-text="sending ? `Trimit ${sendProgress.processed}/${sendProgress.total}…` : `Trimite la eMAG (${pendingCount()})`"></span>
      </button>
    </div>
  </div>

  <!-- Progress bar la trimitere -->
  <template x-if="sending || sendProgress.processed > 0">
    <div class="mb-4 bg-white border border-slate-100 rounded-xl shadow-soft p-4">
      <div class="flex items-center justify-between text-xs text-slate-500 mb-2">
        <span>Procesat <strong x-text="sendProgress.processed"></strong> din <strong x-text="sendProgress.total"></strong></span>
        <span>
          <span class="text-emerald-700">✓ <span x-text="sendProgress.success"></span></span>
          <span class="text-rose-700 ml-2">✗ <span x-text="sendProgress.failed"></span></span>
        </span>
      </div>
      <div class="w-full h-2 bg-slate-100 rounded-full overflow-hidden">
        <div class="h-full bg-gradient-to-r from-emerald-500 to-emerald-600 transition-all duration-300"
             :style="`width: ${sendProgress.total > 0 ? Math.round(sendProgress.processed / sendProgress.total * 100) : 0}%`"></div>
      </div>
    </div>
  </template>

  <!-- ============== APPLY TEMPLATE MODAL ============== -->
  <div x-show="tplOpen" x-cloak @keydown.escape.window="tplOpen = false"
       x-data="{ _bg: false }"
       @mousedown.self="_bg = true"
       @mouseup="if (_bg && $event.target === $el) tplOpen = false; _bg = false"
       class="fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/50 backdrop-blur-sm">
    <div class="modal-enter bg-white rounded-2xl shadow-2xl w-full max-w-4xl max-h-[90vh] flex flex-col">
      <div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between">
        <div>
          <h3 class="font-semibold text-slate-900">Generează titluri din șablon</h3>
          <p class="text-xs text-slate-500 mt-0.5">Va seta <code>new_title</code> pentru <strong x-text="editableCount()"></strong> items editabili. Aplicarea suprascrie noile titluri curente.</p>
        </div>
        <button type="button" @click="tplOpen = false" class="text-slate-400 hover:text-slate-600 p-1">
          <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
        </button>
      </div>

      <div class="p-6 space-y-3 border-b border-slate-100">
        <div class="grid grid-cols-1 md:grid-cols-3 gap-3">
          <div>
            <label class="block text-xs font-medium text-slate-700 mb-1">Alege șablon salvat</label>
            <select x-model="tplTemplateId" @change="onTplSelect()"
              class="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-brand-500">
              <option value="">— sau introdu manual —</option>
              <template x-for="t in templatesList" :key="t.id">
                <option :value="t.id" x-text="t.name"></option>
              </template>
            </select>
          </div>
          <div class="md:col-span-2">
            <label class="block text-xs font-medium text-slate-700 mb-1">Template *</label>
            <input type="text" x-model="tplTemplate" @input.debounce.300ms="refreshTplPreview()"
              placeholder="ex: Husa silicon pentru {brand} {model} {series}"
              class="w-full px-3 py-2 text-sm font-mono border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500">
            <p class="text-xs text-slate-500 mt-1">Placeholders: <code>{brand} {model} {series} {ean} {pnk} {pn} {cod_oblio} {name}</code></p>
          </div>
        </div>
      </div>

      <!-- Preview -->
      <div class="flex-1 overflow-y-auto px-6 py-4">
        <template x-if="tplBusy && tplPreview.length === 0">
          <div class="text-center py-8 text-sm text-slate-400">Calculez preview…</div>
        </template>
        <template x-if="!tplBusy && tplPreview.length === 0 && !tplTemplate.trim()">
          <div class="text-center py-8 text-sm text-slate-400">Introdu un template ca să vezi preview.</div>
        </template>
        <template x-if="tplPreview.length > 0">
          <div class="space-y-2">
            <template x-for="r in tplPreview" :key="r.id">
              <div class="border border-slate-200 rounded-lg overflow-hidden text-xs">
                <div class="px-3 py-1.5 bg-slate-100 border-b border-slate-200 text-slate-600 break-words" x-text="r.old_new || '—'"></div>
                <div class="px-3 py-1.5 bg-emerald-50 text-emerald-900 font-medium break-words" x-text="r.generated || '(gol)'"></div>
              </div>
            </template>
          </div>
        </template>
      </div>

      <div class="px-6 py-4 border-t border-slate-100 bg-slate-50 flex items-center justify-end gap-2 rounded-b-2xl">
        <button type="button" @click="tplOpen = false" class="px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-200 rounded-lg transition">Anulează</button>
        <button type="button" @click="refreshTplPreview()" :disabled="tplBusy || !tplTemplate.trim()"
          class="px-4 py-2 text-sm font-medium text-slate-700 bg-white border border-slate-200 hover:bg-slate-50 rounded-lg transition disabled:opacity-50">
          🔄 Refresh
        </button>
        <button type="button" @click="confirmTplApply()" :disabled="tplBusy || !tplTemplate.trim() || tplPreview.length === 0"
          class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-emerald-600 hover:bg-emerald-700 rounded-lg shadow-soft transition disabled:opacity-50">
          <span x-show="tplBusy" class="spinner"></span>
          Aplică pe <span x-text="editableCount()"></span> items
        </button>
      </div>
    </div>
  </div>

  <!-- Quick apply template (inline) -->
  <div class="bg-white border border-slate-100 rounded-xl shadow-soft p-4 mb-4" x-show="editableCount() > 0">
    <div class="flex flex-col md:flex-row md:items-end gap-3">
      <div class="flex-1 min-w-0">
        <label class="block text-xs font-medium text-slate-700 mb-1">⚡ Aplică șablon rapid</label>
        <select x-model="quickTplId" @change="onQuickTplChange()"
          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="">— alege un șablon salvat —</option>
          <template x-for="t in templatesList" :key="t.id">
            <option :value="t.id" x-text="t.name"></option>
          </template>
        </select>
        <div x-show="quickTplId" class="mt-1.5 text-xs text-slate-500 font-mono break-words" x-text="selectedTplText()"></div>
        <label class="mt-2 inline-flex items-center gap-1.5 text-xs text-slate-600 cursor-pointer select-none">
          <input type="checkbox" x-model="quickRemoveDiacritics" @change="onQuickDiacriticsChange()" class="rounded border-slate-300 text-brand-600 focus:ring-brand-500">
          Fără diacritice (ă→a, ș→s, ț→t — recomandat pentru eMAG)
        </label>
      </div>
      <div class="flex items-center gap-2 flex-shrink-0">
        <button x-show="previewCount() > 0" @click="discardPreview()" type="button"
          class="px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-100 rounded-lg transition" title="Anulează preview-ul">
          Anulează
        </button>
        <button @click="applyQuickTemplate()" :disabled="!quickTplId || quickApplyBusy"
          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-30 disabled:cursor-not-allowed">
          <span x-show="quickApplyBusy" class="spinner"></span>
          <span x-show="!quickApplyBusy && previewCount() > 0" x-text="'✓ Confirmă ' + previewCount() + ' titluri preview'"></span>
          <span x-show="!quickApplyBusy && previewCount() === 0" x-text="'Aplică pe ' + editableCount() + ' items'"></span>
          <span x-show="quickApplyBusy">Aplic…</span>
        </button>
      </div>
    </div>
    <!-- Banner preview activ -->
    <div x-show="previewCount() > 0" x-cloak class="mt-3 bg-brand-50 border border-brand-200 text-brand-800 rounded-lg px-3 py-2 text-xs flex items-center gap-2">
      <svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
      <span><strong x-text="previewCount()"></strong> titluri în PREVIEW (nu sunt salvate). Click <strong>Confirmă</strong> ca să rămână permanente, sau <strong>Anulează</strong> pentru a reveni.</span>
    </div>
    <div x-show="quickApplyMessage" x-cloak class="mt-3 toast-enter bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-lg px-3 py-2 text-xs" x-text="quickApplyMessage"></div>
  </div>

  <!-- Items table -->
  <div class="bg-white border border-slate-100 rounded-xl shadow-soft overflow-hidden">
    <template x-if="items.length === 0">
      <div class="p-10 text-center text-sm text-slate-400">
        Nicio linie în sesiune. Mergi la <a href="<?= url('products.php') ?>" class="text-brand-600 hover:underline">Produse</a>, selectează și folosește bulk action „Adaugă în sesiune".
      </div>
    </template>
    <template x-if="items.length > 0">
      <table class="w-full text-sm">
        <thead class="bg-slate-50 text-xs uppercase tracking-wide text-slate-500">
          <tr class="divide-x divide-slate-200">
            <th class="px-3 py-2.5 text-left font-medium w-12">#</th>
            <th class="px-3 py-2.5 text-left font-medium w-28">Status</th>
            <th class="px-3 py-2.5 text-left font-medium">Titluri (vechi / nou)</th>
            <th class="px-3 py-2.5 text-left font-medium w-28">eMAG ID</th>
            <th class="px-3 py-2.5 text-right font-medium w-12"></th>
          </tr>
        </thead>
        <tbody class="divide-y divide-slate-100">
          <template x-for="(it, idx) in items" :key="it.id">
            <tr class="hover:bg-slate-50/30 divide-x divide-slate-100 align-top">
              <td class="px-3 py-2.5 text-xs text-slate-400 font-mono" x-text="idx + 1"></td>
              <td class="px-3 py-2.5 align-top">
                <span class="inline-flex items-center gap-1 text-[10px] uppercase tracking-wide font-semibold px-2 py-0.5 rounded-full"
                      :class="itemStatusClass(it.sent_status)" x-text="it.sent_status"></span>
                <div x-show="it.error_message" class="text-[10px] text-rose-600 mt-1 break-words" :title="it.error_message" x-text="it.error_message"></div>
                <div x-show="it.sent_at" class="text-[10px] text-slate-400 mt-0.5" x-text="formatDate(it.sent_at)"></div>

                <!-- EAN + PNK cu click-to-copy -->
                <div class="mt-2 space-y-0.5">
                  <div x-show="it.ean" class="flex items-center gap-1 text-[10px]">
                    <span class="text-slate-400 uppercase tracking-wide">EAN</span>
                    <button type="button" @click="copyCell($event, it.ean)"
                      class="font-mono text-slate-700 hover:bg-slate-100 active:bg-slate-200 px-1 rounded transition"
                      :title="'Click pentru a copia: ' + it.ean"
                      x-text="it.ean"></button>
                  </div>
                  <div x-show="it.pnk" class="flex items-center gap-1 text-[10px]">
                    <span class="text-slate-400 uppercase tracking-wide">PNK</span>
                    <button type="button" @click="copyCell($event, it.pnk)"
                      class="font-mono text-slate-700 hover:bg-slate-100 active:bg-slate-200 px-1 rounded transition"
                      :title="'Click pentru a copia: ' + it.pnk"
                      x-text="it.pnk"></button>
                  </div>
                </div>

                <!-- Buton send individual: PERMANENT vizibil (re-send permis după success/error) -->
                <button type="button"
                  x-show="it.new_title && it.new_title.trim() !== '' && !sending"
                  @click="sendSingleItem(it)"
                  :disabled="it.sent_status === 'sending'"
                  class="mt-2 inline-flex items-center gap-1 text-[10px] font-medium px-2 py-1 rounded transition disabled:opacity-50 disabled:cursor-wait"
                  :class="it.sent_status === 'success'
                    ? 'text-sky-700 bg-sky-50 hover:bg-sky-100'
                    : 'text-emerald-700 bg-emerald-50 hover:bg-emerald-100'">
                  <svg x-show="it.sent_status !== 'sending'" class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/></svg>
                  <span x-show="it.sent_status === 'sending'" class="inline-block w-3 h-3 border-2 border-current border-t-transparent rounded-full animate-spin"></span>
                  <span x-text="it.sent_status === 'sending' ? 'Trimit...' : (it.sent_status === 'success' ? 'Re-trimite' : 'Trimite la eMAG')"></span>
                </button>
              </td>
              <!-- Titluri stacked: vechi (gri) sus, separator, nou (verde) jos -->
              <td class="px-2 py-2 align-top">
                <div class="border border-slate-200 rounded-lg overflow-hidden">
                  <!-- Titlu vechi -->
                  <div class="px-3 py-2 bg-slate-100 border-b border-slate-200">
                    <div class="flex items-center gap-1.5 mb-0.5">
                      <span class="text-[9px] uppercase tracking-wider font-semibold text-slate-500">Vechi</span>
                    </div>
                    <div class="text-xs text-slate-600 break-words" x-text="it.old_title || '—'"></div>
                  </div>
                  <!-- Titlu nou -->
                  <div class="px-3 py-2"
                       :class="it._inPreview ? 'bg-brand-50' : 'bg-emerald-50'">
                    <div class="flex items-center gap-1.5 mb-0.5 flex-wrap">
                      <span x-show="!it._inPreview && parseInt(it.is_manual) !== 1" class="text-[9px] uppercase tracking-wider font-semibold text-emerald-700">Nou</span>
                      <span x-show="it._inPreview" class="text-[9px] uppercase tracking-wider font-semibold text-brand-700 bg-brand-100 px-1 rounded">⚡ Preview</span>
                      <button type="button" x-show="parseInt(it.is_manual) === 1" @click="if (confirm('Permite ca șablon să suprascrie acest titlu?')) toggleManual(it)"
                        class="text-[9px] uppercase tracking-wider font-semibold text-amber-800 bg-amber-100 hover:bg-amber-200 px-1 rounded transition"
                        title="Editat manual — protejat de șabloane. Click pentru a permite suprascrierea.">
                        🔒 Manual
                      </button>
                      <span x-show="it._justSaved" x-cloak class="text-[9px] uppercase tracking-wider font-semibold text-emerald-700 bg-emerald-100 px-1 rounded toast-enter">✓ Salvat</span>
                      <span x-show="it.old_title === it.new_title" class="text-[9px] uppercase tracking-wider text-amber-600">⚠ identice</span>
                      <span x-show="hasDiacritics(it.new_title)" class="text-[9px] uppercase tracking-wider text-amber-600" title="Conține diacritice — recomandat pentru eMAG fără">⚠ diacritice</span>
                    </div>
                    <template x-if="it.sent_status !== 'success'">
                      <div>
                        <textarea x-model="it.new_title" @change="saveItemTitle(it)" rows="2"
                          class="w-full px-2 py-1 text-xs bg-white border rounded focus:outline-none focus:ring-1 resize-y min-h-[2.5rem] font-medium"
                          :class="[
                            (it.new_title || '').length > 255
                              ? 'border-rose-400 focus:ring-rose-500 text-rose-900'
                              : (it._inPreview
                                  ? 'border-brand-300 border-dashed focus:ring-brand-500 text-brand-900'
                                  : 'border-emerald-200 focus:ring-emerald-500 text-emerald-900')
                          ]"
                          placeholder="Introdu noul titlu…"></textarea>
                        <div class="flex items-center justify-between mt-1 text-[10px]">
                          <button type="button" @click="stripDiacriticsItem(it)" :disabled="!hasDiacritics(it.new_title)"
                            class="text-emerald-700 hover:text-emerald-900 hover:underline disabled:opacity-30 disabled:cursor-not-allowed"
                            title="Elimină diacriticele din acest titlu">
                            ✨ Curăță diacritice
                          </button>
                          <span :class="(it.new_title || '').length > 255 ? 'text-rose-600 font-semibold' : ((it.new_title || '').length > 230 ? 'text-amber-600' : 'text-slate-400')"
                                x-text="(it.new_title || '').length + ' / 255'"></span>
                        </div>
                      </div>
                    </template>
                    <template x-if="it.sent_status === 'success'">
                      <div>
                        <div class="text-xs text-emerald-900 font-medium break-words" x-text="it.new_title"></div>
                        <div class="text-[10px] text-slate-400 mt-0.5" x-text="(it.new_title || '').length + ' / 255'"></div>
                      </div>
                    </template>
                  </div>
                </div>
              </td>
              <td class="px-3 py-2.5 align-top">
                <div class="font-mono text-[11px] text-slate-500" x-text="it.emag_id || '—'"></div>
                <!-- Phone info: principal + compatibile -->
                <template x-if="it.phone_series_name">
                  <div class="mt-2 text-[10px] leading-tight">
                    <div class="text-slate-700 flex items-start gap-1">
                      <span class="text-amber-500 flex-shrink-0">★</span>
                      <span x-text="[it.phone_brand_name, it.phone_model_name, it.phone_series_name].filter(Boolean).join(' ')"></span>
                    </div>
                    <template x-if="it.phone_compatible_names">
                      <div class="text-slate-400 pl-3 mt-0.5" x-text="'+ ' + it.phone_compatible_names"></div>
                    </template>
                  </div>
                </template>
              </td>
              <td class="px-3 py-2.5 text-right whitespace-nowrap">
                <button @click="revertItem(it)" :disabled="!it.old_title || it.new_title === it.old_title"
                  class="text-amber-600 hover:text-amber-700 p-1 rounded hover:bg-amber-50 transition disabled:opacity-20 disabled:cursor-not-allowed"
                  title="Restaurează titlul nou la cel vechi (snapshot)">
                  <svg 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="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"/></svg>
                </button>
                <button @click="deleteItem(it)" :disabled="it.sent_status === 'success'"
                  class="text-rose-500 hover:text-rose-700 p-1 rounded hover:bg-rose-50 transition disabled:opacity-20 disabled:cursor-not-allowed"
                  title="Scoate din sesiune">
                  <svg 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="M6 18L18 6M6 6l12 12"/></svg>
                </button>
              </td>
            </tr>
          </template>
        </tbody>
      </table>
    </template>
  </div>

</div>

<script>
function sessionDetail({ session, items, templatesList, csrf }) {
  return {
    session,
    items,
    templatesList: templatesList || [],
    csrf,
    sending: false,
    sendProgress: { processed: 0, total: 0, success: 0, failed: 0 },
    // Apply template modal
    tplOpen: false,
    tplTemplate: '',
    tplTemplateId: '',
    tplPreview: [],
    tplBusy: false,
    // Quick apply (inline, fără modal)
    quickTplId: '',
    quickRemoveDiacritics: true,  // default ON — eMAG preferă fără diacritice
    quickApplyBusy: false,
    quickApplyMessage: '',
    revertBusy: false,

    statusBadgeClass(s) {
      return {
        'draft':     'bg-slate-100 text-slate-700',
        'queued':    'bg-sky-100 text-sky-800',
        'sending':   'bg-amber-100 text-amber-800',
        'completed': 'bg-emerald-100 text-emerald-800',
        'partial':   'bg-amber-100 text-amber-800',
        'failed':    'bg-rose-100 text-rose-800',
      }[s] || 'bg-slate-100 text-slate-700';
    },
    itemStatusClass(s) {
      return {
        'pending':  'bg-amber-100 text-amber-800',
        'sending':  'bg-sky-100 text-sky-800',
        'success':  'bg-emerald-100 text-emerald-800',
        'failed':   'bg-rose-100 text-rose-800',
        'skipped':  'bg-slate-100 text-slate-700',
      }[s] || 'bg-slate-100 text-slate-700';
    },
    successCount() { return this.items.filter(x => x.sent_status === 'success').length; },
    failedCount()  { return this.items.filter(x => x.sent_status === 'failed').length; },
    pendingCount() { return this.items.filter(x => x.sent_status === 'pending' && x.new_title && x.new_title.trim() !== '').length; },
    editableCount(){ return this.items.length; }, // toate items pot primi (re)aplicare șablon
    nonSuccessCount(){ return this.items.filter(x => x.sent_status !== 'success').length; },
    successCountAll(){ return this.items.filter(x => x.sent_status === 'success').length; },

    formatDate(s) {
      if (!s) return '';
      const d = new Date(s.replace(' ', 'T'));
      return d.toLocaleDateString('ro-RO') + ' ' + d.toLocaleTimeString('ro-RO', {hour:'2-digit', minute:'2-digit'});
    },

    async saveItemTitle(it) {
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('action', 'update');
        fd.append('id', it.id);
        fd.append('new_title', it.new_title);
        const r = await fetch('<?= url('api/update-session-item.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);
        // Resetez statusul dacă era failed
        if (it.sent_status === 'failed') {
          it.sent_status = 'pending';
          it.error_message = null;
        }
        // Marchez ca manual — sticky pentru template apply
        it.is_manual = 1;
        // Editarea manuală commite preview-ul pentru acest item (devine permanent)
        if (it._inPreview) {
          delete it._original;
          it._inPreview = false;
        }
        // Feedback vizual scurt: badge „salvat" pentru 1.5s
        it._justSaved = true;
        setTimeout(() => { it._justSaved = false; }, 1500);
      } catch (e) {
        alert('Eroare salvare: ' + e.message);
      }
    },

    async toggleManual(it) {
      const newVal = parseInt(it.is_manual) === 1 ? 0 : 1;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('action', 'set_manual');
        fd.append('id', it.id);
        fd.append('is_manual', newVal);
        const r = await fetch('<?= url('api/update-session-item.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);
        it.is_manual = newVal;
      } catch (e) {
        alert('Eroare: ' + e.message);
      }
    },

    async deleteItem(it) {
      if (it.sent_status === 'success') return;
      if (!confirm('Scoți acest item din sesiune?')) return;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('action', 'delete');
        fd.append('id', it.id);
        const r = await fetch('<?= url('api/update-session-item.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);
        this.items = this.items.filter(x => x.id !== it.id);
      } catch (e) {
        alert('Eroare: ' + e.message);
      }
    },

    // ---------- Revert (restaurează new_title la old_title) ----------
    async revertItem(it) {
      if (!it.old_title || it.new_title === it.old_title) return;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('session_id', this.session.id);
        fd.append('item_ids[]', it.id);
        const r = await fetch('<?= url('api/revert-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);
        const updated = (data.items || []).find(x => x.id === it.id);
        if (updated) {
          it.new_title = updated.new_title;
          it.sent_status = updated.sent_status;
          it.error_message = updated.error_message;
        } else {
          it.new_title = it.old_title;
        }
      } catch (e) {
        alert('Eroare revert: ' + e.message);
      }
    },

    // Revert local-only — restaurează new_title = old_title, dar NU trimite la eMAG.
    // Util când vrei să resetezi titlurile pregătite în sesiune fără a atinge eMAG-ul.
    async revertAllLocal() {
      if (this.items.length === 0) return;
      const candidates = this.items.filter(x => x.old_title && x.new_title !== x.old_title);
      if (candidates.length === 0) {
        alert('Nimic de revertat — toate titlurile noi sunt deja egale cu cele vechi.');
        return;
      }
      if (!confirm(`Restaurez ${candidates.length} titluri noi la valoarea originală (snapshot)?\n\nNUMAI local — NU se trimite nimic la eMAG. Produsele success rămân success (DB-ul nu mai e sincron cu ce e pe eMAG).`)) return;

      this.revertBusy = true;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('session_id', this.session.id);
        // Fără reset_success → success items își păstrează statusul
        const r = await fetch('<?= url('api/revert-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);

        for (const upd of (data.items || [])) {
          const it = this.items.find(x => x.id === upd.id);
          if (it) {
            it.new_title = upd.new_title;
            it.sent_status = upd.sent_status;
            it.error_message = upd.error_message;
          }
        }
        alert(`✓ ${data.reverted} titluri revertate local (fără push eMAG).`);
      } catch (e) {
        alert('Eroare revert local: ' + e.message);
      } finally {
        this.revertBusy = false;
      }
    },

    async revertAll() {
      if (this.items.length === 0) return;
      const candidates = this.items.filter(x => x.old_title && x.new_title !== x.old_title);
      const successCount = this.successCountAll();

      if (candidates.length === 0 && successCount === 0) {
        alert('Nimic de revertat — toate titlurile sunt deja egale cu cele vechi.');
        return;
      }

      // Construim mesajul de confirm cu detalii despre rollback
      let msg = `Revert all + rollback eMAG?\n\n`;
      msg += `• ${candidates.length} titluri vor fi restaurate la valoarea originală\n`;
      if (successCount > 0) {
        msg += `• ${successCount} produse cu status SUCCESS vor fi re-trimise la eMAG cu titlul vechi (rollback efectiv)\n`;
      }
      msg += `\nContinui?`;

      if (!confirm(msg)) return;

      this.revertBusy = true;
      try {
        // 1. Revert în DB cu reset_success=1 (success → pending pentru a fi incluse la send)
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('session_id', this.session.id);
        fd.append('reset_success', '1');
        const r = await fetch('<?= url('api/revert-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);

        for (const upd of (data.items || [])) {
          const it = this.items.find(x => x.id === upd.id);
          if (it) {
            it.new_title = upd.new_title;
            it.sent_status = upd.sent_status;
            it.error_message = upd.error_message;
          }
        }

        // 2. Dacă mai sunt itemi de trimis (după revert sunt toți pending) → bulk send pentru rollback
        const toSend = this.pendingCount();
        if (toSend > 0) {
          // Reuse sendAll() pentru push eMAG cu progress bar standard
          await this.sendAll();
        }
        alert(`✓ Revert finalizat (${data.reverted} titluri).` + (toSend > 0 ? `\n${this.sendProgress.success} trimise OK, ${this.sendProgress.failed} eșuate.` : ''));
      } catch (e) {
        alert('Eroare revert all: ' + e.message);
      } finally {
        this.revertBusy = false;
      }
    },

    // ---------- Diacritics helpers ----------
    stripDiacriticsStr(s) {
      // NFD normalize + strip combining marks (U+0300..U+036F). Funcționează pentru
      // română (ă/î/â/ș/ț) și majoritatea diacriticelor EU.
      return (s || '').normalize('NFD').replace(/[̀-ͯ]/g, '');
    },
    hasDiacritics(s) {
      if (!s) return false;
      return this.stripDiacriticsStr(s) !== s;
    },
    async stripDiacriticsItem(it) {
      const cleaned = this.stripDiacriticsStr(it.new_title);
      if (cleaned === it.new_title) return;
      it.new_title = cleaned;
      await this.saveItemTitle(it);
    },

    // ---------- Click-to-copy pe EAN/PNK ----------
    async copyCell(evt, value) {
      if (!value) return;
      const el = evt.currentTarget;
      try {
        if (navigator.clipboard && window.isSecureContext) {
          await navigator.clipboard.writeText(value);
        } else {
          const ta = document.createElement('textarea');
          ta.value = value; ta.style.position = 'fixed'; ta.style.left = '-9999px';
          document.body.appendChild(ta); ta.select();
          document.execCommand('copy');
          document.body.removeChild(ta);
        }
        const original = el.textContent;
        el.textContent = '✓ copiat';
        el.classList.add('!bg-emerald-100', '!text-emerald-700');
        setTimeout(() => {
          el.textContent = original;
          el.classList.remove('!bg-emerald-100', '!text-emerald-700');
        }, 800);
      } catch (e) { console.warn('Copy failed', e); }
    },

    // ---------- Send individual (un singur item) ----------
    async sendSingleItem(it) {
      if (it.sent_status === 'sending') return;
      if (!it.new_title || it.new_title.trim() === '') {
        alert('Titlu nou e gol — completează înainte de trimitere.');
        return;
      }
      it.sent_status = 'sending';
      it.error_message = null;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('session_id', this.session.id);
        fd.append('item_ids[]', it.id);
        fd.append('limit', 1);
        const r = await fetch('<?= url('api/send-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);
        const res = (data.results || []).find(x => x.id === it.id);
        if (res) {
          it.sent_status = res.ok ? 'success' : 'failed';
          it.error_message = res.error || null;
          it.sent_at = new Date().toISOString().slice(0, 19).replace('T', ' ');
        } else {
          // Backend nu a returnat result pentru acest item (poate finalize a fost rulat)
          it.sent_status = 'pending';
        }
      } catch (e) {
        it.sent_status = 'failed';
        it.error_message = e.message;
        alert('Eroare: ' + e.message);
      }
    },

    // ---------- Quick apply cu preview live în tabel ----------
    selectedTplText() {
      const t = this.templatesList.find(x => x.id == this.quickTplId);
      return t ? t.template : '';
    },

    // Câte items sunt acum în preview (modificări nesalvate)
    previewCount() {
      return this.items.filter(x => x._inPreview).length;
    },

    async onQuickTplChange() {
      this.quickApplyMessage = '';
      if (!this.quickTplId) {
        // Selecție goală → discard preview
        this.discardPreview();
        return;
      }
      await this.previewTemplate();
    },

    onQuickDiacriticsChange() {
      // Dacă e activ un preview, re-rulează cu noua opțiune
      if (this.quickTplId) this.previewTemplate();
    },

    // Calculează titlurile preview și le aplică VISUAL pe items (fără save)
    async previewTemplate() {
      if (!this.quickTplId) return;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('action', 'preview');
        fd.append('session_id', this.session.id);
        fd.append('template_id', this.quickTplId);
        if (this.quickRemoveDiacritics) fd.append('remove_diacritics', '1');
        const r = await fetch('<?= url('api/apply-template-to-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);

        for (const res of (data.items || [])) {
          const it = this.items.find(x => x.id === res.id);
          if (!it || !res.generated) continue;
          if (it.sent_status === 'success') continue; // nu suprascriem success-uri în preview
          if (parseInt(it.is_manual) === 1) continue; // nu suprascriem manual edits

          // Salvăm originalul O SINGURĂ DATĂ (la prima preview)
          if (it._original === undefined) {
            it._original = it.new_title;
          }
          it.new_title = res.generated;
          it._inPreview = true;
        }
      } catch (e) {
        console.warn('Preview eșuat:', e.message);
      }
    },

    // Anulează preview-ul vizual: restaurează titlurile la valorile salvate
    discardPreview() {
      for (const it of this.items) {
        if (it._inPreview) {
          it.new_title = it._original;
          delete it._original;
          it._inPreview = false;
        }
      }
    },

    // Confirmă: salvează la backend titlurile preview ca permanente
    async applyQuickTemplate() {
      if (!this.quickTplId) return;
      this.quickApplyBusy = true;
      this.quickApplyMessage = '';
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('action', 'apply');
        fd.append('session_id', this.session.id);
        fd.append('template_id', this.quickTplId);
        if (this.quickRemoveDiacritics) fd.append('remove_diacritics', '1');
        const r = await fetch('<?= url('api/apply-template-to-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);

        // Update items local cu valorile finale + curăță flag-urile de preview
        for (const res of (data.items || [])) {
          const it = this.items.find(x => x.id === res.id);
          if (!it || !res.generated) continue;
          if (res.preserved) continue; // manual edit — NU atinge
          it.new_title = res.generated;
          // Sincronizează status-ul cu cel calculat de backend (success/failed → pending la title change)
          if (res.new_status && res.new_status !== it.sent_status) {
            it.sent_status = res.new_status;
            it.error_message = null;
          }
          delete it._original;
          it._inPreview = false;
        }

        const tplName = this.templatesList.find(t => t.id == this.quickTplId)?.name || 'șablon';
        const parts = [`✓ Aplicat „${tplName}" pe ${data.applied} items`];
        if (data.preserved > 0) parts.push(`${data.preserved} manuale păstrate 🔒`);
        if (data.unchanged > 0) parts.push(`${data.unchanged} neschimbate`);
        if (data.skipped > 0)   parts.push(`${data.skipped} sărite`);
        this.quickApplyMessage = parts.join(' · ');
        setTimeout(() => { this.quickApplyMessage = ''; }, 6000);
      } catch (e) {
        alert('Eroare: ' + e.message);
      } finally {
        this.quickApplyBusy = false;
      }
    },

    // ---------- Apply template (generate new_title pentru items) ----------
    openApplyTemplate() {
      if (this.editableCount() === 0) return;
      this.tplTemplate = '';
      this.tplTemplateId = '';
      this.tplPreview = [];
      this.tplOpen = true;
    },

    onTplSelect() {
      const t = this.templatesList.find(x => x.id == this.tplTemplateId);
      if (t) this.tplTemplate = t.template;
      this.refreshTplPreview();
    },

    async refreshTplPreview() {
      if (!this.tplTemplate.trim()) {
        this.tplPreview = [];
        return;
      }
      this.tplBusy = true;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('action', 'preview');
        fd.append('session_id', this.session.id);
        fd.append('template', this.tplTemplate);
        const r = await fetch('<?= url('api/apply-template-to-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);
        this.tplPreview = data.items;
      } catch (e) {
        alert('Eroare preview: ' + e.message);
      } finally {
        this.tplBusy = false;
      }
    },

    async confirmTplApply() {
      if (!this.tplTemplate.trim()) return;
      this.tplBusy = true;
      try {
        const fd = new FormData();
        fd.append('csrf_token', this.csrf);
        fd.append('action', 'apply');
        fd.append('session_id', this.session.id);
        fd.append('template', this.tplTemplate);
        const r = await fetch('<?= url('api/apply-template-to-session.php') ?>', { method: 'POST', body: fd });
        const data = await r.json();
        if (!data.ok) throw new Error(data.error);

        // Update local items cu new_title generat
        for (const res of (data.items || [])) {
          const it = this.items.find(x => x.id === res.id);
          if (it && res.generated) {
            it.new_title = res.generated;
            // Sincronizează status-ul cu cel calculat de backend (success/failed → pending la title change)
            if (res.new_status && res.new_status !== it.sent_status) {
              it.sent_status = res.new_status;
              it.error_message = null;
            }
          }
        }
        this.tplOpen = false;
        alert(`✓ ${data.applied} titluri generate, ${data.skipped} sărite (gol-uri).`);
      } catch (e) {
        alert('Eroare apply: ' + e.message);
      } finally {
        this.tplBusy = false;
      }
    },

    async confirmSend() {
      const pending = this.pendingCount();
      if (pending === 0) return;
      if (!confirm(`Trimit ${pending} titluri noi la eMAG?\n\nProdusele vor primi noul nume pe contul vânzătorului.`)) return;
      await this.sendAll();
    },

    async sendAll() {
      this.sending = true;
      this.sendProgress = { processed: 0, total: this.pendingCount(), success: 0, failed: 0 };

      try {
        let safety = 200;
        while (safety-- > 0) {
          const fd = new FormData();
          fd.append('csrf_token', this.csrf);
          fd.append('session_id', this.session.id);
          fd.append('limit', 5); // 5 per call ca să raportez progres frecvent

          const r = await fetch('<?= url('api/send-session.php') ?>', { method: 'POST', body: fd });
          const data = await r.json();
          if (!data.ok) throw new Error(data.error);

          this.sendProgress.processed += data.processed;
          this.sendProgress.success   += data.success;
          this.sendProgress.failed    += data.failed;

          // Aplică rezultatele pe items local (real-time fără reload)
          for (const res of (data.results || [])) {
            const it = this.items.find(x => x.id === res.id);
            if (it) {
              it.sent_status = res.ok ? 'success' : 'failed';
              it.error_message = res.error || null;
              it.sent_at = new Date().toISOString().slice(0, 19).replace('T', ' ');
            }
          }

          if (!data.has_more) break;
        }
        // Refresh session status după ce s-a terminat tot
        if (this.sendProgress.failed === 0 && this.sendProgress.success > 0) {
          this.session.status = 'completed';
        } else if (this.sendProgress.failed > 0 && this.sendProgress.success > 0) {
          this.session.status = 'partial';
        } else if (this.sendProgress.failed > 0) {
          this.session.status = 'failed';
        }
      } catch (e) {
        alert('Eroare trimitere: ' + e.message);
      } finally {
        this.sending = false;
      }
    }
  };
}
</script>

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