<?php /* views/pages/disparos.php */


require_once __DIR__ . '/components/tutorial.php';
require_once __DIR__ . '/../../app/license_guard.php';
license_guard_or_die();
?>
<!-- Tutorial -->
<?= tutorial_component([
  'id'       => 'disparador',
  'title'    => 'Como usar Disparos',
  'button'   => 'Ver tutorial de disparos',
  'video'    => 'https://youtu.be/-RrZHHM6TPE',
  'spotlight'=> true
]); ?>

<style>
  /* esconde a scrollbar só visualmente (a rolagem continua) */
  .hide-scrollbar::-webkit-scrollbar { display: none; }
  .hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

  /* NAV do carrossel de pastas (sempre visível) */
  .car-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 20;
    width: 40px; height: 40px;
    border-radius: 9999px;
    display: grid; place-items: center;
    background: white;
    border: 1px solid rgba(0,0,0,.08);
    box-shadow: 0 2px 10px rgba(0,0,0,.10);
    cursor: pointer;
    transition: transform .15s ease, opacity .15s ease, box-shadow .15s ease;
  }
  .car-nav:hover { transform: translateY(-50%) scale(1.05); box-shadow: 0 4px 14px rgba(0,0,0,.14); }
  .car-nav:active { transform: translateY(-50%) scale(0.98); }
  .car-nav[disabled] { opacity: .35; cursor: default; transform: translateY(-50%); }

  .car-left { left: -4px; }
  .car-right { right: -4px; }

  /* gradiente nas bordas para indicar overflow */
  .edge-fade {
    position: absolute; inset-y: 0; width: 48px; z-index: 15; pointer-events: none;
  }
  .edge-left  { left: 0;  background: linear-gradient(90deg, white 0%, rgba(255,255,255,0) 100%); }
  .edge-right { right: 0; background: linear-gradient(270deg, white 0%, rgba(255,255,255,0) 100%); }

  /* dark mode (se estiver usando) */
  .dark .car-nav { background: rgb(17 24 39); border-color: rgb(31 41 55); }
  .dark .edge-left  { background: linear-gradient(90deg, rgb(17 24 39) 0%, rgba(17,24,39,0) 100%); }
  .dark .edge-right { background: linear-gradient(270deg, rgb(17 24 39) 0%, rgba(17,24,39,0) 100%); }
</style>




















<div class="p-6">
    
    
    
    
<div class="max-w-md">

    
    <!-- Campo WhatsApp para Notificações -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
  <div class="px-6 py-4" style="background: linear-gradient(to right, #211743, #8148FA, #75E8FF);">
    <div class="flex items-center gap-3">
      <div class="w-10 h-10 rounded-lg bg-white/20 backdrop-blur-sm flex items-center justify-center">
        <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/>
        </svg>
      </div>
      <div>
        <h2 class="text-lg font-semibold text-white">WhatsApp para Notificações</h2>
        <p class="text-sm text-indigo-100">Receba atualizações sobre suas campanhas</p>
      </div>
    </div>
  </div>
  
  <div class="p-6">
    <div class="flex flex-wrap items-end gap-3">
      <div class="flex-1 min-w-[280px] max-w-md">
        <label class="block text-sm font-medium text-gray-700 mb-2">Número do WhatsApp</label>
        <div class="relative">
          <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
            <svg class="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 24 24">
              <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
            </svg>
          </div>
          <input 
            type="text" 
            id="whatsappNotifications" 
            class="w-full pl-10 pr-3 py-2.5 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all" 
            placeholder="(00) 00000-0000"
            maxlength="15"
          >
        </div>
      </div>
      
      <div class="flex items-center gap-3">
        <button 
          id="btnSaveWhatsapp" 
          class="inline-flex items-center justify-center gap-2 px-6 py-2.5 rounded-lg bg-indigo-600 hover:bg-indigo-700 active:bg-indigo-800 text-white font-medium shadow-sm hover:shadow-md transition-all duration-200"
        >
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
          </svg>
          Salvar
        </button>
        <span id="whatsappMsg" class="text-sm font-medium"></span>
      </div>
    </div>
  </div>
</div>

    </div>

    
    
    
    
    
    
    
    
    
    
    
  <h1 class="text-2xl font-semibold mb-4">Disparos</h1>

  <!-- Criar campanha -->
  <div class="bg-white rounded-lg p-4 shadow mb-6">
    <h2 class="text-lg font-medium mb-3">Nova campanha</h2>

    <form id="formDisparo" class="grid grid-cols-1 md:grid-cols-2 gap-4">
      <div class="md:col-span-2">
        <label class="block text-sm mb-1">Nome da campanha</label>
        <input type="text" name="nome" class="w-full rounded border px-3 py-2" placeholder="Ex: Abertura Setembro" required>
      </div>

      <div>
        <label class="block text-sm mb-1">Delay mínimo (minutos)</label>
        <input type="number" name="min_delay" class="w-full rounded border px-3 py-2" value="6" min="1" required>
      </div>
      <div>
        <label class="block text-sm mb-1">Delay máximo (minutos)</label>
        <input type="number" name="max_delay" class="w-full rounded border px-3 py-2" value="15" min="1" required>
      </div>
      
      
      
      <!-- Janela de envio -->
<!-- Janela de envio -->
<div class="md:col-span-2 grid grid-cols-1 md:grid-cols-3 gap-4">
  <div>
<label class="block text-sm mb-1">
  Disparar entre às: 
  <span class="text-gray-600 font-medium">
    (Pode variar até 3 min para iniciar)
  </span>
</label>
    <input type="time" id="schStart" class="w-full rounded border px-3 py-2" value="09:00">
    <p class="text-xs text-gray-500 mt-1">Formato HH:MM</p>
  </div>
  <div>
<label class="block text-sm mb-1">
  Com término às:
  <span class="font-semibold text-gray-900">
    (Pode variar até 3 min para finalizar)
  </span>
</label>
    <input type="time" id="schEnd" class="w-full rounded border px-3 py-2" value="18:00">
  </div>
  <!-- ⤵️ Apenas oculto, continua no DOM pra reativar depois -->
  <div class="hidden">
    <label class="block text-sm mb-1">Timezone</label>
    <input type="text" id="schTz" class="w-full rounded border px-3 py-2"
           value="America/Sao_Paulo" placeholder="IANA TZ ex: America/Sao_Paulo">
  </div>
</div>


<!-- Não disparar nas datas/dias -->
<div class="md:col-span-2">
<label class="block text-sm mb-1">
  <span class="text-gray-900">
    <b class="text-red-600">Não disparar</b>  nos dias da semana
  </span>
</label>
  <div class="flex flex-wrap gap-3 text-sm">
    <!-- 0=Dom ... 6=Sáb -->
    <label class="inline-flex items-center gap-2"><input type="checkbox" class="schWD" value="0"> Dom</label>
    <label class="inline-flex items-center gap-2"><input type="checkbox" class="schWD" value="1"> Seg</label>
    <label class="inline-flex items-center gap-2"><input type="checkbox" class="schWD" value="2"> Ter</label>
    <label class="inline-flex items-center gap-2"><input type="checkbox" class="schWD" value="3"> Qua</label>
    <label class="inline-flex items-center gap-2"><input type="checkbox" class="schWD" value="4"> Qui</label>
    <label class="inline-flex items-center gap-2"><input type="checkbox" class="schWD" value="5"> Sex</label>
    <label class="inline-flex items-center gap-2"><input type="checkbox" class="schWD" value="6"> Sáb</label>
  </div>
<div class="mt-3 hidden">
  <label class="block text-sm mb-1">Não disparar nestas datas</label>
  <input type="text" id="schDates" class="w-full rounded border px-3 py-2" placeholder="Ex: 2025-12-25, 2026-01-01">
  <p class="text-xs text-gray-500 mt-1">Separe múltiplas datas por vírgula (YYYY-MM-DD).</p>
</div>

</div>

      
      
      

      <!-- Funil publicado -->
      <div class="md:col-span-2">
        <label class="block text-sm mb-1">Funil (opcional)</label>
        <select id="funilSelect" class="w-full rounded border px-3 py-2">
          <option value="">— Sem funil —</option>
        </select>
        <p class="text-xs text-gray-500 mt-1">Selecione um funil publicado para usar como sequência inicial.</p>
      </div>
      
      
      <!-- Coluna do CRM (novo) -->
<div class="md:col-span-2">
  <label class="block text-sm mb-1">
    <span class="inline-flex items-center gap-2">
      <svg class="w-4 h-4 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
      </svg>
      Salvar leads na coluna do CRM (após disparo)
    </span>
  </label>
  <select id="crmStageSelect" class="w-full rounded border px-3 py-2">
    <option value="">— Não mover para o CRM —</option>
  </select>
  <p class="text-xs text-gray-500 mt-1">
    Após o disparo, os leads serão automaticamente movidos para esta coluna no seu CRM Kanban.
  </p>
</div>
      
      

      <!-- Toggle ignore default -->
      <div class="md:col-span-2 flex flex-col gap-2">
        <label class="inline-flex items-center gap-3 select-none">
          <input id="igToggle" type="checkbox" class="peer sr-only">
          <div class="w-11 h-6 rounded-full bg-gray-300 peer-checked:bg-indigo-600 relative transition-colors">
            <div class="absolute top-0.5 left-0.5 w-5 h-5 bg-white rounded-full transition-transform peer-checked:translate-x-5"></div>
          </div>
          <span class="text-sm text-gray-800">
            Ignorar mensagem padrão (a IA só interage após um tempo mínimo de resposta)
          </span>
        </label>

        <div id="igSecondsWrap" class="grid grid-cols-1 md:grid-cols-2 gap-4 hidden">
          <div class="md:col-span-2">
            <label class="block text-sm mb-1">A IA só vai interagir se a resposta da prospecção ocorrer em mais de (segundos)</label>
            <input id="igSeconds" type="number" min="0" step="1" class="w-full rounded border px-3 py-2" placeholder="Ex: 120">
            <p class="text-xs text-gray-500 mt-1">Dica: 0 desativa o tempo. Valor salvo em <code>ignore_timeout_seconds</code>.</p>
          </div>
        </div>
      </div>

      <div class="md:col-span-2">
        <button type="button" id="btnPickLeads" class="rounded bg-gray-800 hover:bg-gray-700 text-white px-4 py-2">
          Selecionar leads…
        </button>
        <span id="pickCount" class="ml-2 text-sm text-gray-600">Nenhum lead selecionado</span>
      </div>

      <div class="md:col-span-2 flex items-center gap-3">
        <button type="submit" class="rounded bg-indigo-600 hover:bg-indigo-500 text-white px-4 py-2">Criar campanha</button>
        <span id="createMsg" class="text-sm text-gray-600"></span>
      </div>
    </form>
  </div>

  <!-- Lista campanhas -->
  <div class="bg-white rounded-lg p-4 shadow">
    <div class="flex items-center justify-between mb-3">
      <h2 class="text-lg font-medium">Minhas campanhas</h2>
      <button id="btnReload" class="rounded bg-gray-800 hover:bg-gray-700 text-white px-3 py-2 text-sm">Atualizar</button>
    </div>
    <div class="overflow-x-auto">
      <table class="min-w-full text-sm">
        <thead>
          <tr class="text-left border-b">
            <th class="py-2 pr-3">Nome</th>
            <th class="py-2 pr-3">Funil</th>
            <th class="py-2 pr-3">Status</th>
            <th class="py-2 pr-3">Total</th>
            <th class="py-2 pr-3">Enviados</th>
            <th class="py-2 pr-3">Erros</th>
            <th class="py-2 pr-3">Sem WhatsApp</th>

            <th class="py-2">Ações</th>
          </tr>
        </thead>
        <tbody id="tbodyCamps"></tbody>
      </table>
    </div>
  </div>
</div>



<!-- Modal motivo da pausa -->
<div id="whyModal" class="fixed inset-0 z-50 hidden">
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-lg rounded-xl bg-white shadow-xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b flex items-center justify-between">
        <h3 class="text-lg font-semibold">Por que sua campanha está pausada?</h3>
        <button id="whyClose" class="text-gray-600 hover:text-black" aria-label="Fechar">&times;</button>
      </div>
      <div class="p-5 text-sm text-gray-800">
        <p class="mb-2">Identificamos que, neste momento, a campanha não pode ser retomada automaticamente porque:</p>
        <ul id="whyList" class="list-disc pl-5 space-y-1"></ul>
        <div id="whyWindow" class="mt-3 text-xs text-gray-600"></div>
      </div>
<div class="px-5 py-4 border-t flex items-center justify-end gap-2">
  <button id="whyEdit" class="px-3 py-2 rounded border">Editar campanha</button>
  <button id="whyOk" class="px-3 py-2 rounded bg-indigo-600 text-white">Entendi</button>
</div>

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





<!-- Modal seleção de leads (com pastas) -->
<div id="leadModal" class="fixed inset-0 bg-black/40 hidden z-50">
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="bg-white rounded-2xl shadow-xl w-full max-w-5xl p-4 border border-gray-200">
      <div class="flex items-center justify-between mb-3">
        <h3 class="text-lg font-semibold">Selecionar leads</h3>
        <button id="closeLeadModal" class="text-gray-600 hover:text-black" aria-label="Fechar">&times;</button>
      </div>

      <!-- Pastas (carrossel horizontal com setas sempre visíveis) -->
      <div class="mb-3">
        <div class="mb-2 text-xs text-gray-500">Pastas</div>
        <div class="relative">
          <!-- fades nas bordas -->
          <div class="edge-fade edge-left"></div>
          <div class="edge-fade edge-right"></div>

          <!-- setas (sempre visíveis) -->
          <button id="mFprev" class="car-nav car-left" title="Anterior" aria-label="Anterior">
            <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M15 18l-6-6 6-6"/>
            </svg>
          </button>
          <button id="mFnext" class="car-nav car-right" title="Próxima" aria-label="Próxima">
            <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M9 6l6 6-6 6"/>
            </svg>
          </button>

          <!-- viewport -->
          <div id="mFoldersViewport" class="overflow-x-auto hide-scrollbar px-6">
            <div id="mFoldersBar" class="flex gap-3 pr-6 snap-x snap-mandatory"></div>
          </div>
        </div>
      </div>

      <!-- Controles de paginação (modal) -->
      <div class="flex items-center gap-2 mb-3">
        <label class="text-sm">Itens por página</label>
        <select id="mPageSize" class="rounded border px-2 py-1 text-sm">
          <option>10</option>
          <option selected>20</option>
          <option>50</option>
        </select>
        <div class="ml-auto flex gap-2">
          <button id="mPrev" class="rounded border px-3 py-1.5 text-sm">Anterior</button>
          <span id="mPageInfo" class="text-sm text-gray-600 self-center">1</span>
          <button id="mNext" class="rounded border px-3 py-1.5 text-sm">Próxima</button>
        </div>
      </div>

      <div class="overflow-x-auto max-h-[60vh]">
        <table class="min-w-full text-sm">
          <thead class="text-left">
            <tr>
              <th class="py-2 pr-3 w-10"><input id="mCheckAll" class="size-4" type="checkbox"></th>
              <th class="py-2 pr-3">Empresa</th>
              <th class="py-2 pr-3">Telefone</th>
              <th class="py-2 pr-3">Criado</th>
            </tr>
          </thead>
          <tbody id="mLeadRows"></tbody>
        </table>
      </div>

      <div class="mt-4 flex items-center justify-between">
        <span id="mSelCount" class="text-sm text-gray-700">0 selecionados</span>
        <div class="flex gap-2">
          <button id="mClear" class="rounded border px-3 py-2 text-sm">Limpar</button>
          <button id="mConfirm" class="rounded bg-indigo-600 hover:bg-indigo-500 text-white px-4 py-2 text-sm">Usar selecionados</button>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- Modal confirmar exclusão -->
<div id="delModal" class="fixed inset-0 z-50 hidden">
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-md rounded-xl bg-white shadow-xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b">
        <h3 class="text-lg font-semibold">Excluir campanha</h3>
      </div>
      <div class="p-5 text-sm text-gray-700">
        <p class="mb-2">
          Tem certeza que deseja excluir a campanha
          <span id="delName" class="font-medium text-gray-900"></span>?
        </p>
        <p class="text-gray-500">Essa ação remove a campanha e <b>todos os leads vinculados</b>. Não é possível desfazer.</p>
      </div>
      <div class="px-5 py-4 border-t flex items-center justify-end gap-2">
        <button id="delCancel" class="px-3 py-2 rounded border">Cancelar</button>
        <button id="delConfirm" class="px-3 py-2 rounded bg-rose-600 text-white">Excluir</button>
      </div>
    </div>
  </div>
</div>

<!-- Modal confirmar início -->
<div id="startModal" class="fixed inset-0 z-50 hidden">
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-md rounded-xl bg-white shadow-xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b">
        <h3 class="text-lg font-semibold">Iniciar campanha</h3>
      </div>
      <div class="p-5 text-sm text-gray-700">
        <p class="mb-2">
          Você está prestes a iniciar a campanha
          <span id="startName" class="font-medium text-gray-900"></span>.
        </p>
        <p class="text-gray-500">Os disparos serão iniciados após sua confirmação.</p>
      </div>
      <div class="px-5 py-4 border-t flex items-center justify-end gap-2">
        <button id="startCancel" class="px-3 py-2 rounded border">Cancelar</button>
        <button id="startConfirm" class="px-3 py-2 rounded bg-green-600 text-white">Iniciar agora</button>
      </div>
    </div>
  </div>
</div>




<!-- Modal confirmar retomada -->
<div id="resumeModal" class="fixed inset-0 z-50 hidden">
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-md rounded-xl bg-white shadow-xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b">
        <h3 class="text-lg font-semibold">Retomar campanha</h3>
      </div>
      <div class="p-5 text-sm text-gray-700">
        <p class="mb-2">
          Você está prestes a retomar a campanha
          <span id="resumeName" class="font-medium text-gray-900"></span>.
        </p>
        <p class="text-gray-500">Os disparos serão reiniciados a partir de onde pararam.</p>
      </div>
      <div class="px-5 py-4 border-t flex items-center justify-end gap-2">
        <button id="resumeCancel" class="px-3 py-2 rounded border">Cancelar</button>
        <button id="resumeConfirm" class="px-3 py-2 rounded bg-blue-600 text-white">Retomar agora</button>
      </div>
    </div>
  </div>
</div>













<!-- Modal erro de conexão -->
<div id="connectionErrorModal" class="fixed inset-0 z-50 hidden">
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-md rounded-xl bg-white shadow-xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b">
        <h3 class="text-lg font-semibold flex items-center gap-2">
          <svg class="w-6 h-6 text-amber-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
          </svg>
          Conexão WhatsApp necessária
        </h3>
      </div>
      <div class="p-5">
        <p class="text-sm text-gray-700 mb-3" id="connErrorMessage"></p>
        <div class="rounded-lg bg-blue-50 border border-blue-200 p-3">
          <p class="text-xs text-blue-800 font-medium mb-1">💡 Como resolver:</p>
          <ol class="text-xs text-blue-700 space-y-1 pl-4 list-decimal">
            <li>Acesse a aba <strong>Conexões</strong></li>
            <li>Exclua sua conexão atual <strong>(Caso tenha)</strong></li>
            <li>Crie uma nova conexão, e gere o QR Code e conecte seu WhatsApp</li>
            <li>Aguarde até aparecer <strong>"Connected"</strong></li>
            <li>Volte e inicie sua campanha</li>
          </ol>
        </div>
      </div>
      <div class="px-5 py-4 border-t flex items-center justify-end gap-2">
        <button id="connErrorClose" class="px-3 py-2 rounded border">Fechar</button>
        <button id="connErrorGoTo" class="px-3 py-2 rounded bg-indigo-600 text-white">Ir para Conexões</button>
      </div>
    </div>
  </div>
</div>





<!-- Modal FALHA DE CONEXÃO DETECTADA (bloqueante) -->
<div id="connFailureModal" class="fixed inset-0 z-[60] hidden">
  <div class="absolute inset-0 bg-black/70 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-md rounded-xl bg-white shadow-2xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b bg-rose-50">
        <h3 class="text-lg font-semibold flex items-center gap-2 text-rose-900">
          <svg class="w-6 h-6 text-rose-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
          </svg>
          Falha na conexão WhatsApp
        </h3>
      </div>
      <div class="p-5">
        <p class="text-sm text-gray-800 mb-3">
          Detectamos que sua conexão WhatsApp falhou durante os disparos da campanha
          <span id="connFailureName" class="font-semibold text-gray-900"></span>.
        </p>
        <p class="text-sm text-gray-700 mb-3">
          Para continuar, você precisa reconectar seu WhatsApp.
        </p>
        <div class="rounded-lg bg-blue-50 border border-blue-200 p-3">
          <p class="text-xs text-blue-800 font-medium mb-1">💡 O que fazer:</p>
          <ol class="text-xs text-blue-700 space-y-1 pl-4 list-decimal">
            <li>Clique em <strong>"Ir para Conexões"</strong> abaixo</li>
            <li>Exclua sua conexão atual</li>
            <li>Crie uma nova conexão e escaneie o QR Code</li>
            <li>Aguarde até aparecer <strong>"Connected"</strong></li>
            <li>Volte aqui e retome sua campanha</li>
          </ol>
        </div>
      </div>
      <div class="px-5 py-4 border-t flex items-center justify-center">
        <button id="connFailureGoTo" class="px-6 py-2.5 rounded-lg bg-rose-600 hover:bg-rose-700 text-white font-medium shadow-sm transition-all">
          Ir para Conexões
        </button>
      </div>
    </div>
  </div>
</div>







<!-- Modal Detalhes da campanha -->
<div id="detModal" class="fixed inset-0 z-50 hidden">
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-5xl rounded-2xl bg-white shadow-xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b flex items-center justify-between">
        <h3 class="text-lg font-semibold">Detalhes da campanha</h3>
        <button id="detClose" class="text-gray-600 hover:text-black" aria-label="Fechar">&times;</button>
      </div>

      <div class="p-5">
        <!-- Header/resumo -->
        <div id="detHeader" class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"></div>

        <!-- Badges -->
        <div id="detBadges" class="flex flex-wrap gap-2 mb-4"></div>

        <!-- Tabela de leads (paginada) -->
        <div class="border rounded-lg">
          <div class="px-3 py-2 border-b flex items-center justify-between">
            <div class="text-sm font-medium">Leads da campanha</div>
            <div class="flex items-center gap-2">
              <label class="text-xs">Itens por página</label>
              <select id="detPageSize" class="rounded border px-2 py-1 text-xs">
                <option>10</option>
                <option selected>20</option>
                <option>50</option>
                <option>100</option>
              </select>
              <button id="detPrev" class="rounded border px-2 py-1 text-xs">Anterior</button>
              <span id="detPageInfo" class="text-xs text-gray-600">1</span>
              <button id="detNext" class="rounded border px-2 py-1 text-xs">Próxima</button>
            </div>
          </div>
          <div class="overflow-x-auto max-h-[60vh]">
            <table class="min-w-full text-sm">
              <thead class="text-left sticky top-0 bg-white">
                <tr>
                  <th class="py-2 px-3">ID</th>
                  <th class="py-2 px-3">Empresa</th>
                  <th class="py-2 px-3">Telefone</th>
                  <th class="py-2 px-3">Status</th>
                  <th class="py-2 px-3">Criado</th>
                  <th class="py-2 px-3">Pasta</th>
                </tr>
              </thead>
              <tbody id="detRows"></tbody>
            </table>
          </div>
        </div>
      </div>

      <div class="px-5 py-4 border-t flex items-center justify-end">
        <button id="detClose2" class="px-3 py-2 rounded border">Fechar</button>
      </div>
    </div>
  </div>
</div>


<!-- Modal Editar campanha -->
<div id="editModal" class="fixed inset-0 z-50 hidden">
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  <div class="absolute inset-0 flex items-center justify-center p-4">
    <div class="w-full max-w-xl rounded-xl bg-white shadow-xl ring-1 ring-black/5">
      <div class="px-5 py-4 border-b flex items-center justify-between">
        <h3 class="text-lg font-semibold">Editar campanha</h3>
        <button id="editClose" class="text-gray-600 hover:text-black" aria-label="Fechar">&times;</button>
      </div>
      <div class="p-5 grid grid-cols-1 md:grid-cols-2 gap-4">
        <div class="md:col-span-2">
          <label class="block text-sm mb-1">Nome</label>
          <input id="edNome" type="text" class="w-full rounded border px-3 py-2">
        </div>
        <div>
          <label class="block text-sm mb-1">Delay mínimo (min)</label>
          <input id="edMin" type="number" min="1" class="w-full rounded border px-3 py-2">
        </div>
        <div>
          <label class="block text-sm mb-1">Delay máximo (min)</label>
          <input id="edMax" type="number" min="1" class="w-full rounded border px-3 py-2">
        </div>

        <div class="md:col-span-2">
          <label class="inline-flex items-center gap-2 select-none">
            <input id="edIgnToggle" type="checkbox" class="size-4">
            <span class="text-sm">Ignorar mensagem padrão</span>
          </label>
          <div id="edIgnWrap" class="mt-2">
            <label class="block text-sm mb-1">IA só interage se resposta demorar mais que (segundos)</label>
            <input id="edIgnSecs" type="number" min="0" step="1" class="w-full rounded border px-3 py-2" placeholder="Ex: 120">
          </div>
        </div>

        <div class="md:col-span-2 grid grid-cols-1 md:grid-cols-3 gap-4">
          <div>
            <label class="block text-sm mb-1">Disparar entre</label>
            <input id="edSchStart" type="time" class="w-full rounded border px-3 py-2">
          </div>
          <div>
            <label class="block text-sm mb-1">Até</label>
            <input id="edSchEnd" type="time" class="w-full rounded border px-3 py-2">
          </div>
<div class="hidden">
  <label class="block text-sm mb-1">Timezone</label>
  <input id="edSchTz" type="text" class="w-full rounded border px-3 py-2" value="America/Sao_Paulo">
</div>

          <div class="md:col-span-3">
            <label class="block text-sm mb-1">Não disparar nos dias:</label>
            <div class="flex flex-wrap gap-3 text-sm" id="edSchWeekdays"></div>
          </div>
<div class="md:col-span-3 hidden">
  <label class="block text-sm mb-1">Não disparar nestas datas (YYYY-MM-DD)</label>
  <input id="edSchDates" type="text" class="w-full rounded border px-3 py-2" placeholder="Ex: 2025-12-25, 2026-01-01">
</div>

        </div>

        <div class="md:col-span-2 text-sm text-gray-500">
          <b>Aviso:</b> edição não altera os leads nem o funil já anexado; afeta somente
          nome/delays e filtro padrão.
        </div>
      </div>
      <div class="px-5 py-4 border-t flex items-center justify-end gap-2">
        <button id="editCancel" class="px-3 py-2 rounded border">Cancelar</button>
        <button id="editSave" class="px-3 py-2 rounded bg-indigo-600 text-white">Salvar alterações</button>
      </div>
    </div>
  </div>
</div>













<script>
  // Carrega opções de funil publicado
  async function loadFunis() {
    const selFunil = document.getElementById('funilSelect');
    if (!selFunil) return;
    const r = await fetch('api/funis.php?action=list_options', {credentials:'same-origin'});
    const j = await r.json().catch(()=>({ok:false}));
    if (!j.ok) return;
    selFunil.innerHTML = `<option value="">— Sem funil —</option>` +
      (j.data||[]).map(f=>`<option value="${f.id}">${f.nome} (v${f.versao})</option>`).join('');
  }
  loadFunis();
  
  
  
  
  function fmtTimeRange(sch){
  if (!sch) return '—';
  const tz = sch.tz || 'America/Sao_Paulo';
  const start = sch.start || '—';
  const end   = sch.end   || '—';
  return `${start} – ${end} (${tz})`;
}
function fmtWeekdays(blocked){
  const map = ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'];
  const arr = (blocked||[]).map(n => map[Number(n)]).filter(Boolean);
  return arr.length ? arr.join(', ') : 'Nenhum';
}
function badge(label, tone='gray'){
  const colors = {
    gray:   'bg-gray-100 text-gray-800',
    blue:   'bg-blue-100 text-blue-800',
    green:  'bg-emerald-100 text-emerald-800',
    red:    'bg-rose-100 text-rose-800',
    amber:  'bg-amber-100 text-amber-800',
    indigo: 'bg-indigo-100 text-indigo-800',
    violet: 'bg-violet-100 text-violet-800'
  };
  return `<span class="inline-flex items-center gap-1 px-2 py-1 rounded text-xs ${colors[tone]||colors.gray}">${label}</span>`;
}

  
  
  function minutesFromHHMM(s){
  if(!s || !/^\d{2}:\d{2}$/.test(s)) return null;
  const [h,m] = s.split(':').map(n=>parseInt(n,10));
  return h*60 + m;
}
function nowPartsInTZ(tz){
  const parts = new Intl.DateTimeFormat('en-CA',{
    timeZone: tz, year:'numeric', month:'2-digit', day:'2-digit',
    weekday:'short', hour:'2-digit', minute:'2-digit', hour12:false
  }).formatToParts(new Date());
  const get = t => parts.find(p=>p.type===t)?.value || '';
  const y = get('year'), mo = get('month'), d = get('day');
  const wd = get('weekday'); const h = get('hour'), mi = get('minute');
  const map = {Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};
  return {
    yyyy_mm_dd: `${y}-${mo}-${d}`,
    weekdayIndex: map[wd] ?? null,
    minutes: (parseInt(h,10)*60) + parseInt(mi,10)
  };
}
function weekdayPt(n){ return ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'][n] ?? String(n); }

function explainPauseReasons(campaign){
  const reasons = [];
  const sch = campaign?.schedule || null;
  if(!sch){ return { reasons, windowLabel: null }; }

  const tz = sch.tz || 'America/Sao_Paulo';
  const now = nowPartsInTZ(tz);

  // Dia da semana bloqueado
  const blockedW = (sch.blocked_weekdays||[]).map(Number);
  if (blockedW.includes(now.weekdayIndex)) {
    reasons.push(`Hoje (${weekdayPt(now.weekdayIndex)}) está marcado como “Não disparar”.`);
  }

  // Data específica bloqueada
  const blockedDates = (sch.blocked_dates||[]);
  if (blockedDates.includes(now.yyyy_mm_dd)) {
    reasons.push(`A data de hoje (${now.yyyy_mm_dd}) está na lista de “Não disparar”.`);
  }

  // Janela de horário
  const startMin = minutesFromHHMM(sch.start||'');
  const endMin   = minutesFromHHMM(sch.end||'');
  let windowLabel = null;
  if (startMin!=null && endMin!=null) {
    windowLabel = `Janela configurada: ${sch.start} – ${sch.end} (${tz})`;
    if (now.minutes < startMin) reasons.push(`Está antes do horário de início (${sch.start}).`);
    else if (now.minutes > endMin) reasons.push(`Passou do horário de término (${sch.end}).`);
  }

  return { reasons, windowLabel };
}

  
  
  
  

  function escAttr(s) {
    return String(s ?? '').replaceAll('&','&amp;').replaceAll('"','&quot;').replaceAll('<','&lt;');
  }

  (function () {
    const API_DISPAROS = 'api/disparos.php';
    const API_LEADS    = 'api/leads.php';

    // seleção global (persiste entre páginas/pastas)
    const sel = new Set();

    // Toggle ignore
    const igToggle = document.getElementById('igToggle');
    const igSecondsWrap = document.getElementById('igSecondsWrap');
    const igSeconds = document.getElementById('igSeconds');
    function updateIgUI() {
      if (!igToggle) return;
      if (igToggle.checked) { igSecondsWrap.classList.remove('hidden'); igSeconds.disabled = false; }
      else { igSecondsWrap.classList.add('hidden'); igSeconds.disabled = true; }
    }
    if (igToggle) { igToggle.addEventListener('change', updateIgUI); updateIgUI(); }

    // ---------- Modal de Leads (com pastas) ----------
    const modal = document.getElementById('leadModal');
    const openBtn = document.getElementById('btnPickLeads');
    const closeBtn = document.getElementById('closeLeadModal');

    const mFoldersViewport = document.getElementById('mFoldersViewport');
    const mFprev = document.getElementById('mFprev');
    const mFnext = document.getElementById('mFnext');
    const mFoldersBar = document.getElementById('mFoldersBar');

    const mRows = document.getElementById('mLeadRows');
    const mCheckAll = document.getElementById('mCheckAll');
    const mPageSize = document.getElementById('mPageSize');
    const mPrev = document.getElementById('mPrev');
    const mNext = document.getElementById('mNext');
    const mPageInfo = document.getElementById('mPageInfo');
    const mSelCount = document.getElementById('mSelCount');
    const mClear = document.getElementById('mClear');
    const mConfirm = document.getElementById('mConfirm');
    const pickCount = document.getElementById('pickCount');
    
    
    
    
    
    
    // --- Detalhes modal ---
const detModal = document.getElementById('detModal');
const detClose = document.getElementById('detClose');
const detClose2 = document.getElementById('detClose2');
const detHeader = document.getElementById('detHeader');
const detBadges = document.getElementById('detBadges');
const detRows = document.getElementById('detRows');
const detPageSize = document.getElementById('detPageSize');
const detPrev = document.getElementById('detPrev');
const detNext = document.getElementById('detNext');
const detPageInfo = document.getElementById('detPageInfo');

let detState = { id: null, page: 1, limit: 20, total: 0 };
function openDetModal(){ detModal.classList.remove('hidden'); }
function closeDetModal(){ detModal.classList.add('hidden'); detState = { id:null, page:1, limit:20, total:0 }; }
detClose?.addEventListener('click', closeDetModal);
detClose2?.addEventListener('click', closeDetModal);
detModal?.addEventListener('click', e => { if (e.target === detModal || e.target.classList.contains('backdrop-blur-sm')) closeDetModal(); });
document.addEventListener('keydown', e => { if (!detModal.classList.contains('hidden') && e.key==='Escape') closeDetModal(); });

    // --- Edit modal ---
const editModal  = document.getElementById('editModal');
const editClose  = document.getElementById('editClose');
const editCancel = document.getElementById('editCancel');
const editSave   = document.getElementById('editSave');

const edNome     = document.getElementById('edNome');
const edMin      = document.getElementById('edMin');
const edMax      = document.getElementById('edMax');
const edIgnToggle= document.getElementById('edIgnToggle');
const edIgnWrap  = document.getElementById('edIgnWrap');
const edIgnSecs  = document.getElementById('edIgnSecs');

const edSchStart = document.getElementById('edSchStart');
const edSchEnd   = document.getElementById('edSchEnd');
const edSchTz    = document.getElementById('edSchTz');
const edSchWeek  = document.getElementById('edSchWeekdays');
const edSchDates = document.getElementById('edSchDates');


// --- Why paused modal ---
const whyModal  = document.getElementById('whyModal');
const whyList   = document.getElementById('whyList');
const whyWindow = document.getElementById('whyWindow');
const whyClose  = document.getElementById('whyClose');
const whyOk     = document.getElementById('whyOk');
const whyEdit  = document.getElementById('whyEdit');


function openWhyModal(reasons, windowLabel, campaignId){
  whyList.innerHTML = reasons.map(r=>`<li>${r}</li>`).join('') || '<li>Campanha foi pausada manualmente.</li>';
  whyWindow.textContent = windowLabel || '';
  // limpa handler anterior pra evitar múltiplos binds
  if (whyEdit) {
    whyEdit.onclick = async () => {
      closeWhyModal();
      // abre o modal de edição carregando dados da campanha
      if (campaignId) await openEditFor(campaignId);
    };
  }
  whyModal.classList.remove('hidden');
}

function closeWhyModal(){ whyModal.classList.add('hidden'); }
whyClose?.addEventListener('click', closeWhyModal);
whyOk?.addEventListener('click', closeWhyModal);
whyModal?.addEventListener('click', e=>{
  if(e.target===whyModal || e.target.classList.contains('backdrop-blur-sm')) closeWhyModal();
});
document.addEventListener('keydown', e=>{
  if(!whyModal.classList.contains('hidden') && e.key==='Escape') closeWhyModal();
});




let editState = { id: null };

function openEditModal(){ editModal.classList.remove('hidden'); }
function closeEditModal(){ editModal.classList.add('hidden'); editState.id=null; }

editClose?.addEventListener('click', closeEditModal);
editCancel?.addEventListener('click', closeEditModal);
editModal?.addEventListener('click', e => {
  if (e.target === editModal || e.target.classList.contains('backdrop-blur-sm')) closeEditModal();
});
document.addEventListener('keydown', e => {
  if (!editModal.classList.contains('hidden') && e.key === 'Escape') closeEditModal();
});

function renderWeekdayChecks(selected = []) {
  const items = [
    { v: 0, label: 'Dom' },
    { v: 1, label: 'Seg' },
    { v: 2, label: 'Ter' },
    { v: 3, label: 'Qua' },
    { v: 4, label: 'Qui' },
    { v: 5, label: 'Sex' },
    { v: 6, label: 'Sáb' },
  ];
  edSchWeek.innerHTML = items.map(({ v, label }) => {
    const ck = selected.includes(Number(v)) ? 'checked' : '';
    return `<label class="inline-flex items-center gap-2">
      <input type="checkbox" class="edWD size-4" value="${v}" ${ck}> ${label}
    </label>`;
  }).join(' ');
}


function setEditFields(camp) {
  edNome.value = camp.nome || '';
edMin.value = String((camp.min_delay ?? 1));
edMax.value = String((camp.max_delay ?? 1));


  edIgnToggle.checked = !!camp.ignore_default_message;
  edIgnSecs.value     = String(camp.ignore_timeout_seconds || 0);
  edIgnWrap.classList.toggle('opacity-50', !edIgnToggle.checked);
  edIgnSecs.disabled = !edIgnToggle.checked;

  edIgnToggle.addEventListener('change', ()=>{
    edIgnWrap.classList.toggle('opacity-50', !edIgnToggle.checked);
    edIgnSecs.disabled = !edIgnToggle.checked;
    if (!edIgnToggle.checked) edIgnSecs.value = '0';
  }, { once:true });

  const sch = camp.schedule || null;
  if (sch) {
    edSchStart.value = sch.start || '';
    edSchEnd.value   = sch.end   || '';
    edSchTz.value    = sch.tz    || 'America/Sao_Paulo';
    renderWeekdayChecks((sch.blocked_weekdays||[]).map(Number));
    edSchDates.value = (sch.blocked_dates||[]).join(', ');
  } else {
    edSchStart.value = '';
    edSchEnd.value   = '';
    edSchTz.value    = 'America/Sao_Paulo';
    renderWeekdayChecks([]);
    edSchDates.value = '';
  }
}

async function openEditFor(id){
  // Reusa o endpoint details para preencher o modal
  const qs = new URLSearchParams({ action:'details', id:String(id), page:'1', limit:'1' });
  const d = await fetchJSON(`api/disparos.php?${qs.toString()}`);
  if (!d.ok) { alert(d.error||'Falha ao carregar'); return; }
  const c = d.campaign || {};
  editState.id = c.id;
  setEditFields(c);
  openEditModal();
}

async function saveEdit(){
  if (!editState.id) return;
  const payload = {
    id: editState.id,
    nome: edNome.value.trim(),
    min_delay: Math.max(1, parseInt(edMin.value||'1',10)),
    max_delay: Math.max(1, parseInt(edMax.value||'1',10)),
    ignore_default_message: !!edIgnToggle.checked,
    ignore_timeout_seconds: Math.max(0, parseInt(edIgnSecs.value||'0',10)),
  };

  // schedule
  const s = (edSchStart.value||'').trim();
  const e = (edSchEnd.value||'').trim();
  const t = (edSchTz.value||'America/Sao_Paulo').trim();
  const w = [...document.querySelectorAll('.edWD:checked')].map(i=>parseInt(i.value,10));
  const datesRaw = (edSchDates.value||'').trim();
  const blockedDates = datesRaw ? datesRaw.split(',').map(s=>s.trim()).filter(Boolean) : [];

  if (s && e) {
    payload.schedule = {
      tz: t || 'America/Sao_Paulo',
      start: s,
      end: e,
      blocked_weekdays: w,
      blocked_dates: blockedDates
    };
  } else {
    payload.schedule = null; // limpa a agenda se não preencher ambos
  }

  editSave.disabled = true;
  editSave.textContent = 'Salvando...';
  try {
    const r = await fetch('api/disparos.php?action=update', {
      method:'POST',
      headers:{ 'Content-Type':'application/json' },
      credentials:'same-origin',
      body: JSON.stringify(payload)
    });
    const j = await r.json().catch(()=>({ok:false}));
    if (!j.ok) { alert(j.error||'Falha ao salvar'); }
    else { closeEditModal(); await loadCamps(); }
  } finally {
    editSave.disabled = false;
    editSave.textContent = 'Salvar alterações';
  }
}
editSave?.addEventListener('click', saveEdit);

    
    
    
    
    
    
    
    
    
    
    
    
    
    

    let mPage = 1, mTotal = 0, mSize = parseInt(mPageSize.value, 10);
    let mCurFolder = ''; // '', 'none' ou id (string)
    let mFoldersCache = []; // {id,name,count}
    let mNoneCount = 0;

    function updateSelCount() {
      mSelCount.textContent = `${sel.size} selecionados`;
      pickCount.textContent = sel.size ? `${sel.size} lead(s) selecionado(s)` : 'Nenhum lead selecionado';
    }

    async function fetchJSON(url, opts = {}) {
      const r = await fetch(url, { credentials: 'same-origin', cache: 'no-store', ...opts });
      const t = await r.text();
      let j; try { j = JSON.parse(t); } catch {}
      if (!r.ok || !j) return { ok: false, error: j?.error || t || 'Falha' };
      return j;
    }

    // ---- helpers para carrossel ----
    const nextFrame = () => new Promise(res =>
      requestAnimationFrame(() => requestAnimationFrame(res))
    );

    function mUpdateFolderArrows(){
      if (!mFoldersViewport) return;
      const atStart = mFoldersViewport.scrollLeft <= 2;
      const atEnd   = (mFoldersViewport.scrollLeft + mFoldersViewport.clientWidth) >= (mFoldersViewport.scrollWidth - 2);
      if (mFprev) mFprev.disabled = atStart;
      if (mFnext) mFnext.disabled = atEnd;
    }
    
    
    
    async function loadDetailsPage(id, page, limit){
  const qs = new URLSearchParams({ action:'details', id:String(id), page:String(page), limit:String(limit) });
  const d = await fetchJSON(`api/disparos.php?${qs.toString()}`);
  if (!d.ok) { detHeader.innerHTML = `<div class="text-sm text-rose-700">${d.error||'Falha ao carregar'}</div>`; return; }

  const c   = d.campaign || {};
  const sch = c.schedule || null;
  const fun = c.funil_snapshot || null;
  const st  = d.stats || {};
  const L   = d.leads || { page:1, limit:limit, total:0, data:[] };

  // Header resumido
  detHeader.innerHTML = `
    <div class="bg-gray-50 rounded-lg p-3">
      <div class="text-xs text-gray-500">Nome</div>
      <div class="text-sm font-medium">${escAttr(c.nome||'—')}</div>
      <div class="mt-2 grid grid-cols-2 gap-2 text-xs text-gray-600">
        <div><span class="text-gray-500">ID:</span> ${c.id||'—'}</div>
        <div><span class="text-gray-500">Criado:</span> ${c.created_at ? new Date(c.created_at).toLocaleString() : '—'}</div>
      </div>
    </div>
    <div class="bg-gray-50 rounded-lg p-3">
      <div class="text-xs text-gray-500">Funil</div>
      <div class="text-sm font-medium">${fun?.nome ? `${escAttr(fun.nome)} (v${fun.versao||1})` : 'Disparo por IA/Padrão'}</div>
      ${fun?.sequencia ? `<div class="text-xs text-gray-600 mt-1">${Array.isArray(fun.sequencia)? fun.sequencia.length : 0} etapa(s)</div>` : ''}
    </div>
  `;

  // Badges (status + janela + bloqueios + flags)
  const badges = [];
  badges.push(badge(`status: ${c.status||'—'}`, c.status==='running'?'green':(c.status==='paused'?'amber':'gray')));
  badges.push(badge(`janela: ${fmtTimeRange(sch)}`, 'indigo'));
  if (sch?.blocked_weekdays?.length) badges.push(badge(`não disparar: ${fmtWeekdays(sch.blocked_weekdays)}`, 'violet'));
  if (sch?.blocked_dates?.length) badges.push(badge(`datas vetadas: ${sch.blocked_dates.join(', ')}`, 'violet'));
  if (c.ignore_default_message) badges.push(badge(`filtro padrão: ${c.ignore_timeout_seconds||0}s`, 'blue'));
  // contadores
  badges.push(badge(`Total itens: ${st.total||0}`, 'gray'));
  badges.push(badge(`Pendentes: ${st.pending||0}`, 'gray'));
  badges.push(badge(`Enviados: ${st.sent||0}`, 'green'));
  if ((st.error||0) > 0) badges.push(badge(`Erros: ${st.error}`, 'red'));
  if ((st.sem_whatsapp||0) > 0) badges.push(badge(`Sem WhatsApp: ${st.sem_whatsapp}`, 'amber'));
  detBadges.innerHTML = badges.join(' ');

  // Leads table
  detRows.innerHTML = (L.data||[]).map(r => `
    <tr class="border-t">
      <td class="py-2 px-3">${r.id}</td>
      <td class="py-2 px-3">${escAttr(r.company_name||'—')}</td>
      <td class="py-2 px-3">${escAttr(r.telefone||'—')}</td>
      <td class="py-2 px-3">${escAttr(r.status||'—')}</td>
      <td class="py-2 px-3">${r.lead_created_at ? new Date(r.lead_created_at).toLocaleString() : '—'}</td>
      <td class="py-2 px-3">${escAttr(r.folder_name || (r.folder_id ?? '—'))}</td>
    </tr>
  `).join('') || `<tr><td class="py-3 px-3" colspan="6">Nenhum lead</td></tr>`;

  // paginação
  detState.id = c.id;
  detState.page = L.page;
  detState.limit = L.limit;
  detState.total = L.total;

  const last = Math.max(1, Math.ceil((L.total||0) / L.limit));
  detPageInfo.textContent = `${L.page} / ${last}`;
  detPrev.disabled = (L.page <= 1);
  detNext.disabled = (L.page >= last);
}
detPrev?.addEventListener('click', () => loadDetailsPage(detState.id, detState.page-1, detState.limit));
detNext?.addEventListener('click', () => loadDetailsPage(detState.id, detState.page+1, detState.limit));
detPageSize?.addEventListener('change', () => {
  const lim = parseInt(detPageSize.value, 10) || 20;
  loadDetailsPage(detState.id, 1, lim);
});

    
    
    
    
    

    function mScrollFolders(dir){ // dir = -1 (esq) ou +1 (dir)
      if (!mFoldersViewport) return;
      const vw = mFoldersViewport.getBoundingClientRect().width || mFoldersViewport.clientWidth || 0;
      const step = Math.max(240, Math.round(vw * 0.9)); // fallback para primeira medição
      mFoldersViewport.scrollBy({ left: dir * step, behavior: 'smooth' });
      setTimeout(mUpdateFolderArrows, 160);
    }

    mFprev?.addEventListener('click', () => mScrollFolders(-1));
    mFnext?.addEventListener('click', () => mScrollFolders(+1));
    mFoldersViewport?.addEventListener('scroll', mUpdateFolderArrows);
    mFoldersViewport?.addEventListener('wheel', (e) => {
      if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {
        e.preventDefault();
        mFoldersViewport.scrollLeft += e.deltaY;
        mUpdateFolderArrows();
      }
    }, { passive: false });
    window.addEventListener('resize', mUpdateFolderArrows);

    // Pastas do modal
    async function mLoadFolders(){
      const d = await fetchJSON(`${API_LEADS}?action=folders.list`);
      if (!d.ok) return;
      const counts = d.counts || {};
      mFoldersCache = (d.folders || []).map(f => ({ id:String(f.id), name:f.name, count: counts[String(f.id)] || 0 }));
      mNoneCount = d.none || 0;
      mRenderFoldersBar();
      await nextFrame(); // garante layout antes de calcular setas
      mUpdateFolderArrows();
    }

    function mFolderIcon(){
      return `
        <svg viewBox="0 0 24 24" fill="none" class="w-full h-full">
          <path d="M3.5 6.75A1.75 1.75 0 0 1 5.25 5h4.19c.46 0 .9.19 1.21.52l1.1 1.13c.31.33.75.52 1.21.52h4.79A1.75 1.75 0 0 1 19.5 9v7.25A2.75 2.75 0 0 1 16.75 19h-9.5A2.75 2.75 0 0 1 4.5 16.25v-8.5Z" stroke="currentColor" class="text-indigo-500" stroke-width="1.5"/>
          <path d="M4.5 9.75h15" stroke="currentColor" stroke-width="1.5" class="text-indigo-400"/>
        </svg>
      `;
    }

    function mRenderFoldersBar(){
      mFoldersBar.innerHTML = '';
      const tile = (label, count, value) => {
        const active = (mCurFolder === value) || (value==='' && mCurFolder==='');
        return `
          <button data-value="${value}"
            class="shrink-0 snap-start group flex flex-col justify-between items-start p-3 rounded-2xl border
                   ${active ? 'border-indigo-500 bg-indigo-50' : 'border-gray-200 hover:border-indigo-400'}
                   w-44 h-28 transition">
            <span class="w-12 h-10 text-indigo-500">${mFolderIcon()}</span>
            <div>
              <div class="text-sm font-medium leading-tight">${label}</div>
              <div class="text-xs text-gray-500">${count} lead(s)</div>
            </div>
          </button>
        `;
      };
      const total = mFoldersCache.reduce((s,f)=>s+f.count, 0) + mNoneCount;
      mFoldersBar.insertAdjacentHTML('beforeend', tile('Todas', total, ''));
      mFoldersBar.insertAdjacentHTML('beforeend', tile('Sem pasta', mNoneCount, 'none'));
      mFoldersCache.forEach(f => mFoldersBar.insertAdjacentHTML('beforeend', tile(f.name, f.count, f.id)));

      mFoldersBar.querySelectorAll('button').forEach(btn => {
        btn.addEventListener('click', async e => {
          mCurFolder = e.currentTarget.getAttribute('data-value') || '';
          mRenderFoldersBar();
          await mLoadPage(1);
          mUpdateFolderArrows();
        });
      });
    }

    // Listagem dentro do modal respeitando pasta
    async function mLoadPage(page = 1) {
      mPage = page;
      mSize = parseInt(mPageSize.value, 10);
      const qs = new URLSearchParams({ action:'list', page:String(mPage), limit:String(mSize) });
      if (mCurFolder !== '') qs.set('folder_id', mCurFolder);
      const d = await fetchJSON(`${API_LEADS}?${qs.toString()}`);

      if (!d.ok) {
        mRows.innerHTML = `<tr><td class="py-3" colspan="6">Erro: ${d.error}</td></tr>`;
        return;
      }

      mTotal = d.total || 0;
      mPageInfo.textContent = `${d.page} / ${Math.max(1, Math.ceil(mTotal/mSize))}`;
      mPrev.disabled = (d.page <= 1);
      mNext.disabled = (d.page >= Math.ceil(mTotal / mSize));

      mRows.innerHTML = (d.data || []).map(it => {
        const checked = sel.has(it.id) ? 'checked' : '';
        return `
          <tr class="border-t">
            <td class="py-2 pr-3"><input type="checkbox" data-id="${it.id}" class="mRow size-4" ${checked}></td>
            <td class="py-2 pr-3">${it.company || '—'}</td>
            <td class="py-2 pr-3">${it.phone || '—'}</td>
            <td class="py-2 pr-3">${new Date(it.created_at).toLocaleString()}</td>
          </tr>
        `;
      }).join('') || `<tr><td class="py-3" colspan="6">Nenhum lead</td></tr>`;

      // linhas -> seleção
      mRows.querySelectorAll('.mRow').forEach(cb => {
        cb.addEventListener('change', e => {
          const id = parseInt(e.target.getAttribute('data-id'), 10);
          if (e.target.checked) sel.add(id); else sel.delete(id);
          updateSelCount();
          mUpdateMaster();
        });
      });

      // master
      mUpdateMaster();
    }

    function mUpdateMaster(){
      const boxes = mRows.querySelectorAll('.mRow');
      const total = boxes.length;
      const checked = [...boxes].filter(b => b.checked).length;
      mCheckAll.checked = (total > 0 && checked === total);
      mCheckAll.indeterminate = (checked > 0 && checked < total);
    }

    if (mCheckAll) {
      mCheckAll.addEventListener('change', () => {
        const boxes = mRows.querySelectorAll('.mRow');
        boxes.forEach(cb => {
          const id = parseInt(cb.getAttribute('data-id'), 10);
          cb.checked = mCheckAll.checked;
          if (mCheckAll.checked) sel.add(id); else sel.delete(id);
        });
        updateSelCount();
        mUpdateMaster();
      });
    }

    if (mPrev) mPrev.addEventListener('click', () => mLoadPage(mPage - 1));
    if (mNext) mNext.addEventListener('click', () => mLoadPage(mPage + 1));
    if (mPageSize) mPageSize.addEventListener('change', () => mLoadPage(1));
    if (mClear) mClear.addEventListener('click', () => { sel.clear(); updateSelCount(); mLoadPage(mPage); });

    if (openBtn) openBtn.addEventListener('click', async () => {
      modal.classList.remove('hidden');
      await nextFrame(); // garante largura do viewport > 0
      await mLoadFolders();
      await mLoadPage(1);
      // nudge de 1px previne stuck em alguns browsers
      if (mFoldersViewport) {
        mFoldersViewport.scrollLeft += 1;
        mFoldersViewport.scrollLeft -= 1;
      }
      mUpdateFolderArrows();
    });
    if (closeBtn) closeBtn.addEventListener('click', () => modal.classList.add('hidden'));
    if (mConfirm) mConfirm.addEventListener('click', () => { modal.classList.add('hidden'); updateSelCount(); });

    // ---------- Modais de ação (delete / start) ----------
    const delModal = document.getElementById('delModal');
    const delNameEl = document.getElementById('delName');
    const delCancel = document.getElementById('delCancel');
    const delConfirm = document.getElementById('delConfirm');
    let delId = null;

    function openDeleteModal(id, name) {
      delId = id;
      delNameEl.textContent = `#${id} — ${name || ''}`;
      delConfirm.disabled = false;
      delConfirm.textContent = 'Excluir';
      delModal.classList.remove('hidden');
    }
    function closeDeleteModal() { delModal.classList.add('hidden'); delId = null; }
    if (delCancel) delCancel.addEventListener('click', closeDeleteModal);
    if (delModal) delModal.addEventListener('click', (e) => {
      if (e.target === delModal || e.target.classList.contains('backdrop-blur-sm')) closeDeleteModal();
    });
    document.addEventListener('keydown', (e) => {
      if (!delModal.classList.contains('hidden') && e.key === 'Escape') closeDeleteModal();
    });
    if (delConfirm) delConfirm.addEventListener('click', async () => {
      if (!delId) return;
      delConfirm.disabled = true;
      delConfirm.textContent = 'Excluindo…';
      await campAction(delId, 'delete');
      closeDeleteModal();
    });

    const startModal = document.getElementById('startModal');
    const startNameEl = document.getElementById('startName');
    const startCancel = document.getElementById('startCancel');
    const startConfirm = document.getElementById('startConfirm');
    let startId = null;

    function openStartModal(id, name) {
      startId = id;
      startNameEl.textContent = `#${id} — ${name || ''}`;
      startConfirm.disabled = false;
      startConfirm.textContent = 'Iniciar agora';
      startModal.classList.remove('hidden');
    }
    function closeStartModal() { startModal.classList.add('hidden'); startId = null; }
    if (startCancel) startCancel.addEventListener('click', closeStartModal);
    if (startModal) startModal.addEventListener('click', (e) => {
      if (e.target === startModal || e.target.classList.contains('backdrop-blur-sm')) closeStartModal();
    });
    document.addEventListener('keydown', (e) => {
      if (!startModal.classList.contains('hidden') && e.key === 'Escape') closeStartModal();
    });
if (startConfirm) startConfirm.addEventListener('click', async () => {
  if (!startId) return;
  
  // Desabilita botões e mostra loading
  startConfirm.disabled = true;
  startCancel.disabled = true;
  
  // Salva texto original
  const originalText = startConfirm.textContent;
  
  // Mostra animação de loading com pontos
  let dots = '';
  const loadingInterval = setInterval(() => {
    dots = dots.length >= 3 ? '' : dots + '.';
    startConfirm.textContent = `Iniciando${dots}`;
  }, 400);
  
  try {
    const body = new URLSearchParams({ id: String(startId) });
    const r = await fetch(`${API_DISPAROS}?action=start`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body,
      credentials: 'same-origin'
    });
    
    const j = await r.json();
    
    if (!j.ok) {
      clearInterval(loadingInterval);
      if (j.error === 'connection_missing' || j.error === 'connection_not_open') {
        closeStartModal();
        openConnectionErrorModal(j.message);
      } else {
        alert(j.error || 'Falha ao iniciar campanha');
      }
      startConfirm.disabled = false;
      startCancel.disabled = false;
      startConfirm.textContent = originalText;
      return;
    }
    
    clearInterval(loadingInterval);
    await loadCamps();
    closeStartModal();
    
  } catch (error) {
    clearInterval(loadingInterval);
    console.error('Erro ao iniciar:', error);
    alert('Erro inesperado ao iniciar campanha');
    startConfirm.disabled = false;
    startCancel.disabled = false;
    startConfirm.textContent = originalText;
  }
});




// ====== Modal Retomar ======
const resumeModal = document.getElementById('resumeModal');
const resumeNameEl = document.getElementById('resumeName');
const resumeCancel = document.getElementById('resumeCancel');
const resumeConfirm = document.getElementById('resumeConfirm');
let resumeId = null;

function openResumeModal(id, name) {
  resumeId = id;
  resumeNameEl.textContent = `#${id} — ${name || ''}`;
  resumeConfirm.disabled = false;
  resumeConfirm.textContent = 'Retomar agora';
  resumeModal.classList.remove('hidden');
}

function closeResumeModal() {
  resumeModal.classList.add('hidden');
  resumeId = null;
}

resumeCancel?.addEventListener('click', closeResumeModal);
resumeModal?.addEventListener('click', (e) => {
  if (e.target === resumeModal || e.target.classList.contains('backdrop-blur-sm')) {
    closeResumeModal();
  }
});

document.addEventListener('keydown', (e) => {
  if (!resumeModal.classList.contains('hidden') && e.key === 'Escape') {
    closeResumeModal();
  }
});

resumeConfirm?.addEventListener('click', async () => {
  if (!resumeId) return;
  
  // Desabilita botão e mostra loading
  resumeConfirm.disabled = true;
  resumeCancel.disabled = true;
  
  // Salva texto original
  const originalText = resumeConfirm.textContent;
  
  // Mostra animação de loading com pontos
  let dots = '';
  const loadingInterval = setInterval(() => {
    dots = dots.length >= 3 ? '' : dots + '.';
    resumeConfirm.textContent = `Retomando${dots}`;
  }, 400);
  
  try {
    // ========= VERIFICAÇÃO DE FALHA DE CONEXÃO =========
    // Antes de tudo, checa se há flag falha_connection = true
    const checkR = await fetch('api/disparos.php?action=check_connection_failure&_=' + Date.now(), {
      credentials: 'same-origin',
      cache: 'no-store'
    });
    const checkJ = await checkR.json();
    
    if (checkJ.ok && checkJ.has_failure) {
      clearInterval(loadingInterval);
      closeResumeModal();
      
      // Abre o modal bloqueante de falha de conexão
      connFailureName.textContent = `#${checkJ.campaign_id} — ${checkJ.campaign_nome || ''}`;
      connFailureModal.classList.remove('hidden');
      
      // Para o polling enquanto o modal está aberto
      if (connFailureCheckInterval) {
        clearInterval(connFailureCheckInterval);
        connFailureCheckInterval = null;
      }
      return;
    }
    
    // Primeiro carrega os detalhes para verificar agenda/bloqueios
    const qs = new URLSearchParams({ action:'details', id:String(resumeId), page:'1', limit:'1' });
    const d = await fetchJSON(`api/disparos.php?${qs.toString()}`);
    
    if (!d.ok) {
      clearInterval(loadingInterval);
      alert(d.error||'Falha ao carregar');
      resumeConfirm.disabled = false;
      resumeCancel.disabled = false;
      resumeConfirm.textContent = originalText;
      return;
    }
    
    const campaign = d.campaign || {};
    const { reasons, windowLabel } = explainPauseReasons(campaign);
    
    // Se houver bloqueio de agenda, mostra modal explicativo
    if (reasons.length > 0) {
      clearInterval(loadingInterval);
      closeResumeModal();
      openWhyModal(reasons, windowLabel, resumeId);
      return;
    }

    // Tenta retomar a campanha
    const body = new URLSearchParams({ id: String(resumeId) });
    const r = await fetch(`${API_DISPAROS}?action=resume`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body,
      credentials: 'same-origin'
    });
    
    const j = await r.json();
    
    if (!j.ok) {
      clearInterval(loadingInterval);
      // Verifica se é erro de conexão WhatsApp
      if (j.error === 'connection_missing' || j.error === 'connection_not_open') {
        closeResumeModal();
        openConnectionErrorModal(j.message || 'Conexão WhatsApp inativa.');
      } else {
        alert(j.error || 'Falha ao retomar campanha');
      }
      resumeConfirm.disabled = false;
      resumeCancel.disabled = false;
      resumeConfirm.textContent = originalText;
      return;
    }
    
    clearInterval(loadingInterval);
    await loadCamps();
    closeResumeModal();
    
  } catch (error) {
    clearInterval(loadingInterval);
    console.error('Erro ao retomar:', error);
    alert('Erro inesperado ao retomar campanha');
    resumeConfirm.disabled = false;
    resumeCancel.disabled = false;
    resumeConfirm.textContent = originalText;
  }
});

















    // ---------- Lista de campanhas ----------
    async function loadCamps() {
      const tb = document.getElementById('tbodyCamps');
      tb.innerHTML = '<tr><td class="py-3" colspan="8">Carregando...</td></tr>';

      const d = await fetchJSON(`${API_DISPAROS}?action=list&_=${Date.now()}`);
      if (!d.ok) {
        tb.innerHTML = `<tr><td class="py-3" colspan="8">${d.error}</td></tr>`;
        return;
      }

      tb.innerHTML = (d.data || []).map(c => {
const sent  = Number(c.enviados || 0);
const err   = Number(c.erros || 0);
const semWhats = Number(c.sem_whatsapp || 0);
const total = Number(c.total || 0);
const done  = total > 0 && (sent + err + semWhats) >= total;

        let actions = '';
        if (done) {
          actions = `
  <button data-act="details" data-id="${c.id}"
    class="px-2 py-1 rounded bg-gray-200 hover:bg-gray-300 text-gray-900 mr-1">Detalhes</button>
  <span class="inline-flex items-center gap-1 rounded bg-emerald-100 text-emerald-800 px-2 py-1 text-xs">
    <svg xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor">
      <path d="M20 6L9 17l-5-5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
    Disparos concluídos
  </span>
  <button data-act="delete" data-id="${c.id}" data-name="${escAttr(c.nome)}"
          class="ml-2 px-2 py-1 rounded bg-rose-600 text-white">Excluir</button>
`;

        } else {
          const btns = [];
          if (c.status === 'draft')
            btns.push(`<button data-act="start" data-id="${c.id}" data-name="${escAttr(c.nome)}"
              class="px-2 py-1 rounded bg-green-600 text-white mr-1">Iniciar</button>`);
         if (c.status === 'paused')
  btns.push(`<button data-act="resume" data-id="${c.id}" data-name="${escAttr(c.nome)}"
    class="px-2 py-1 rounded bg-blue-600 text-white mr-1">Retomar</button>`);
          if (c.status === 'running')
            btns.push(`<button data-act="pause" data-id="${c.id}"
              class="px-2 py-1 rounded bg-yellow-600 text-white mr-1">Pausar</button>`);
              
              
           if (['draft','paused','running'].includes(c.status)) {
            btns.push(`<button data-act="edit" data-id="${c.id}" data-name="${escAttr(c.nome)}"
                class="px-2 py-1 rounded bg-indigo-600 text-white mr-1">Editar</button>`);
            }
   
              
          if (c.status !== 'running')
            btns.push(`<button data-act="delete" data-id="${c.id}" data-name="${escAttr(c.nome)}"
              class="px-2 py-1 rounded bg-rose-600 text-white">Excluir</button>`);
          btns.push(`<button data-act="refresh" data-id="${c.id}"
              class="px-2 py-1 rounded bg-gray-700 text-white ml-1">Atualizar</button>`);
              
          btns.unshift(`<button data-act="details" data-id="${c.id}"
  class="px-2 py-1 rounded bg-gray-200 hover:bg-gray-300 text-gray-900 mr-1">Detalhes</button>`);
    
              
          actions = btns.join(' ');
        }

        return `
          <tr class="border-b">
            <td class="py-2 pr-3">
              ${c.nome}
              ${c.ignore_default_message ? `<span title="Ignorar mensagem padrão: ativo (> ${c.ignore_timeout_seconds}s)" class="ml-2 text-[11px] px-1.5 py-0.5 rounded bg-indigo-100 text-indigo-800 align-middle">filtro: ${c.ignore_timeout_seconds}s</span>` : ''}
            </td>
            <td class="py-2 pr-3">${c.funil_nome || 'Disparo por IA/Padrão'}</td>
            <td class="py-2 pr-3">${done ? 'finished' : c.status}</td>
            <td class="py-2 pr-3">${c.total}</td>
            <td class="py-2 pr-3">${c.enviados}</td>
            <td class="py-2 pr-3">${c.erros}</td>
            <td class="py-2 pr-3">${semWhats || 0}</td>

            <td class="py-2">${actions}</td>
          </tr>
        `;
      }).join('') || '<tr><td class="py-3" colspan="8">Nenhuma campanha</td></tr>';
    }

    async function campAction(id, action) {
      const body = new URLSearchParams({ id: String(id) });
      const r = await fetch(`${API_DISPAROS}?action=${action}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body,
        credentials: 'same-origin'
      });
      const j = await r.json();
      if (!j.ok) alert(j.error || 'Falha na ação');
      await loadCamps();
    }

    async function refreshStats(id) {
      try { await fetch(`${API_DISPAROS}?action=stats&id=${id}`, { credentials: 'same-origin' }); }
      catch (e) { console.error(e); }
    }

document.getElementById('tbodyCamps').addEventListener('click', async (ev) => {
  const b = ev.target.closest('button');
  if (!b) return;

  const id  = b.getAttribute('data-id');
  const act = b.getAttribute('data-act');

  if (act === 'refresh') { await refreshStats(id); await loadCamps(); return; }
  if (act === 'delete')  { openDeleteModal(id, b.getAttribute('data-name') || ''); return; }
  if (act === 'start')   { openStartModal(id, b.getAttribute('data-name') || ''); return; }

  if (act === 'details') {
    openDetModal();
    const lim = parseInt(detPageSize?.value || '20', 10) || 20;
    await loadDetailsPage(id, 1, lim);
    return;
  }

  // ⬇️ FALTAVA ESTE CASE
  if (act === 'edit') {
    await openEditFor(id); // carrega o details, preenche e abre o modal de edição
    return;
  }
  
  
if (act === 'resume') {
  openResumeModal(id, b.getAttribute('data-name') || '');
  return;
}
  
  
  
  
  

  if (act) await campAction(id, act);
});


    document.getElementById('btnReload').addEventListener('click', loadCamps);

    // Submit da campanha
    document.getElementById('formDisparo').addEventListener('submit', async (ev) => {
      ev.preventDefault();
      if (sel.size === 0) { alert('Selecione ao menos 1 lead.'); return; }

      const fd = new FormData(ev.currentTarget);
      const enableIgnore = !!document.getElementById('igToggle')?.checked;
      let secs = 0;
      if (enableIgnore) {
        const v = parseInt(document.getElementById('igSeconds').value || '0', 10);
        secs = isNaN(v) || v < 0 ? 0 : v;
      }

      // funil pode ser UUID (não parsear)
      const selFunilEl = document.getElementById('funilSelect');
      let funil_id = null;
      if (selFunilEl && selFunilEl.value && selFunilEl.value.trim() !== '') {
        funil_id = selFunilEl.value.trim();
      }

      const payload = {
        nome: fd.get('nome'),
        min_delay: Number(fd.get('min_delay') || 2),
        max_delay: Number(fd.get('max_delay') || 6),
        lead_ids: [...sel],
        ignore_default_message: enableIgnore,
        ignore_timeout_seconds: secs,
        funil_id: funil_id,
        crm_stage_id: document.getElementById('crmStageSelect')?.value || null // ⬅️ NOVO

      };
      
      
      // --- NOVO: schedule ---
const schStart = (document.getElementById('schStart')?.value || '').trim();
const schEnd   = (document.getElementById('schEnd')?.value || '').trim();
const schTz    = (document.getElementById('schTz')?.value || 'America/Sao_Paulo').trim();

const wds = [...document.querySelectorAll('.schWD:checked')].map(i => parseInt(i.value, 10));
let datesRaw = (document.getElementById('schDates')?.value || '').trim();
const blockedDates = datesRaw ? datesRaw.split(',').map(s => s.trim()).filter(Boolean) : [];

if (schStart && schEnd) {
  payload.schedule = {
    tz: schTz || 'America/Sao_Paulo',
    start: schStart,
    end: schEnd,
    blocked_weekdays: wds,
    blocked_dates: blockedDates
  };
}

      
      
      
      

      const msg = document.getElementById('createMsg');
      msg.textContent = 'Criando campanha...';

      const r = await fetch(`${API_DISPAROS}?action=create`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
        credentials: 'same-origin'
      });
      const j = await r.json();
      if (j.ok) {
        msg.textContent = `Campanha #${j.id} criada com ${j.total} números.`;
        const url = new URL(window.location.href);
        url.searchParams.set('page', 'disparos');
        url.searchParams.set('_', Date.now());
        setTimeout(() => {
          window.location.replace(url.toString());
          setTimeout(() => { window.location.href = url.toString(); }, 50);
          setTimeout(() => { window.location.reload(); }, 300);
        }, 80);
      } else {
        msg.textContent = 'Erro: ' + (j.error || 'Falha');
      }
    });
    
    
    
    
    
    // Modal de erro de conexão
const connErrorModal = document.getElementById('connectionErrorModal');
const connErrorMessage = document.getElementById('connErrorMessage');
const connErrorClose = document.getElementById('connErrorClose');
const connErrorGoTo = document.getElementById('connErrorGoTo');

function openConnectionErrorModal(message) {
  connErrorMessage.textContent = message;
  connErrorModal.classList.remove('hidden');
}

function closeConnectionErrorModal() {
  connErrorModal.classList.add('hidden');
}

connErrorClose?.addEventListener('click', closeConnectionErrorModal);
connErrorGoTo?.addEventListener('click', () => {
  window.location.href = '?page=conexoes';
});
connErrorModal?.addEventListener('click', (e) => {
  if (e.target === connErrorModal || e.target.classList.contains('backdrop-blur-sm')) {
    closeConnectionErrorModal();
  }
}); // ✅ ADICIONE ESTE FECHAMENTO
    
    
    
    
    // ========= CARREGAR COLUNAS DO CRM =========
async function loadCRMStages() {
  const select = document.getElementById('crmStageSelect');
  if (!select) return;
  
  try {
    const r = await fetch('api/crm.php?action=board_meta', {
      credentials: 'same-origin'
    });
    const j = await r.json();
    
    if (j.ok && j.stages) {
      select.innerHTML = '<option value="">— Não mover para o CRM —</option>';
      
      j.stages.forEach(stage => {
        const option = document.createElement('option');
        option.value = stage.id;
        option.textContent = `${stage.name} (${stage.total || 0} leads)`;
        select.appendChild(option);
      });
    }
  } catch (error) {
    console.error('Erro ao carregar colunas do CRM:', error);
  }
}

// Carrega colunas do CRM no boot
loadCRMStages();
    
    
    
    

    // Boot
    (function boot() {
      mSelCount.textContent = '0 selecionados';
      updateSelCount();
      loadCamps();
    })();
  })();
  
  
  
  
// ========= MÁSCARA WHATSAPP =========
function maskWhatsApp(value) {
  value = value.replace(/\D/g, ''); // Remove tudo que não é dígito
  value = value.replace(/^(\d{2})(\d)/g, '($1) $2'); // Coloca parênteses em volta dos 2 primeiros dígitos
  value = value.replace(/(\d)(\d{4})$/, '$1-$2'); // Coloca hífen entre o 4º e o 5º dígitos
  return value;
}

// Aplica máscara no campo
const whatsappInput = document.getElementById('whatsappNotifications');
if (whatsappInput) {
  whatsappInput.addEventListener('input', (e) => {
    e.target.value = maskWhatsApp(e.target.value);
  });
}

// ========= SALVAR WHATSAPP =========
async function saveWhatsAppNotification() {
  const input = document.getElementById('whatsappNotifications');
  const btn = document.getElementById('btnSaveWhatsapp');
  const msg = document.getElementById('whatsappMsg');
  
  if (!input || !btn || !msg) return;
  
  const whatsapp = input.value.trim();
  
  // Validação básica
  const digitsOnly = whatsapp.replace(/\D/g, '');
  if (digitsOnly.length < 10 || digitsOnly.length > 11) {
    msg.textContent = 'Número inválido';
    msg.className = 'text-sm text-rose-600';
    return;
  }
  
  btn.disabled = true;
  btn.textContent = 'Salvando...';
  msg.textContent = '';
  
  try {
    const response = await fetch('api/user.php?action=update_whatsapp', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      credentials: 'same-origin',
      body: JSON.stringify({ whatsapp_notifications: whatsapp })
    });
    
    const result = await response.json();
    
    if (result.ok) {
      msg.textContent = '✓ WhatsApp salvo com sucesso!';
      msg.className = 'text-sm text-emerald-600';
    } else {
      msg.textContent = 'Erro: ' + (result.error || 'Falha ao salvar');
      msg.className = 'text-sm text-rose-600';
    }
  } catch (error) {
    msg.textContent = 'Erro ao salvar';
    msg.className = 'text-sm text-rose-600';
  } finally {
    btn.disabled = false;
    btn.textContent = 'Salvar';
    setTimeout(() => { msg.textContent = ''; }, 3000);
  }
}

// Evento do botão salvar
document.getElementById('btnSaveWhatsapp')?.addEventListener('click', saveWhatsAppNotification);

// ========= CARREGAR WHATSAPP ATUAL =========
async function loadCurrentWhatsApp() {
  try {
    const response = await fetch('api/user.php?action=get_whatsapp', {
      credentials: 'same-origin'
    });
    const result = await response.json();
    
    if (result.ok && result.whatsapp) {
      const input = document.getElementById('whatsappNotifications');
      if (input) {
        input.value = maskWhatsApp(result.whatsapp);
      }
    }
  } catch (error) {
    console.error('Erro ao carregar WhatsApp:', error);
  }
}

// Chame no boot
loadCurrentWhatsApp();  
  
  
  
  
  
  
  // ========= DETECÇÃO DE FALHA DE CONEXÃO =========
const connFailureModal = document.getElementById('connFailureModal');
const connFailureName = document.getElementById('connFailureName');
const connFailureGoTo = document.getElementById('connFailureGoTo');

let connFailureCheckInterval = null;

async function checkConnectionFailure() {
  try {
    const r = await fetch('api/disparos.php?action=check_connection_failure&_=' + Date.now(), {
      credentials: 'same-origin',
      cache: 'no-store'
    });
    const j = await r.json();
    
    if (j.ok && j.has_failure) {
      // Mostra o modal bloqueante
      connFailureName.textContent = `#${j.campaign_id} — ${j.campaign_nome || ''}`;
      connFailureModal.classList.remove('hidden');
      
      // Para o polling enquanto o modal está aberto
      if (connFailureCheckInterval) {
        clearInterval(connFailureCheckInterval);
        connFailureCheckInterval = null;
      }
    }
  } catch (error) {
    console.error('Erro ao verificar falha de conexão:', error);
  }
}

// Botão "Ir para Conexões": limpa o flag e redireciona
connFailureGoTo?.addEventListener('click', async () => {
  connFailureGoTo.disabled = true;
  const originalText = connFailureGoTo.textContent;
  connFailureGoTo.textContent = 'Aguarde...';
  
  try {
    // Limpa o flag falha_connection no banco
    await fetch('api/disparos.php?action=clear_connection_failure', {
      method: 'POST',
      credentials: 'same-origin'
    });
  } catch (error) {
    console.error('Erro ao limpar flag:', error);
  } finally {
    // Redireciona para conexões mesmo se der erro
    window.location.href = '?page=conexoes';
  }
});

// BLOQUEIOS: impedir fechar por ESC ou clique no backdrop
// (não adicionamos listeners de fechar — modal permanece travado)

// Inicia verificação: ao carregar a página + polling a cada 15 segundos
checkConnectionFailure();
connFailureCheckInterval = setInterval(checkConnectionFailure, 15000);
  
  
  
  
  
</script>
