<?php
require_once(dirname(__DIR__) . '/config/db.php');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

$titulo = "Integrações de Realizado";
$icone = "bi-arrow-left-right";

$filtro = $_GET['status'] ?? 'ativas';
$order = $_GET['order'] ?? 'cdintegracao';
$dir = strtolower($_GET['dir'] ?? 'asc');
$dir = $dir === 'desc' ? 'desc' : 'asc';
$nextDir = $dir === 'asc' ? 'desc' : 'asc';
$limit = (int)($_GET['limit'] ?? 100);
$page = (int)($_GET['page'] ?? 1);
$offset = ($page - 1) * $limit;
$busca = trim($_GET['busca'] ?? '');

$where = [];
$params = [];
if ($filtro === 'ativas') $where[] = "flativo = true";
elseif ($filtro === 'inativas') $where[] = "flativo = false";
if ($busca) {
    $where[] = "(dsintegracao ILIKE :busca OR host ILIKE :busca OR dbname ILIKE :busca)";
    $params[':busca'] = "%$busca%";
}
$whereSql = $where ? "WHERE " . implode(" AND ", $where) : "";
$limitSql = ($limit === -1) ? "" : "LIMIT $limit OFFSET $offset";

$sql = "SELECT cdintegracao, dsintegracao, flativo, fltipo, tipo_banco, host, porta, dbname, schema_banco,
               schedule_cron, schedule_ativo, ultima_sincronizacao, sql_origem, api_token_hash
        FROM back.integracao
        $whereSql
        ORDER BY $order $dir
        $limitSql";

$stmt = $pdo->prepare($sql);
foreach ($params as $k => $v) $stmt->bindValue($k, $v);
$stmt->execute();
$integracoes = $stmt->fetchAll(PDO::FETCH_ASSOC);

$sqlCount = "SELECT COUNT(*) FROM back.integracao $whereSql";
$stmtCount = $pdo->prepare($sqlCount);
foreach ($params as $k => $v) $stmtCount->bindValue($k, $v);
$stmtCount->execute();
$total = $stmtCount->fetchColumn();

$tipos_banco = ['pgsql' => 'PostgreSQL', 'mysql' => 'MySQL', 'sqlsrv' => 'SQL Server'];
$empresas = $pdo->query("SELECT cdempresa, dsempresa, dsapelido FROM back.empresa WHERE flativo = 0 ORDER BY dsempresa")->fetchAll(PDO::FETCH_ASSOC);

// Buscar integrações do tipo 'conexao' ou 'api' ativas para uso como fonte de dados nas integrações "origem"
$integracoesFonte = $pdo->query("SELECT cdintegracao, dsintegracao, fltipo, tipo_banco, host, dbname FROM back.integracao WHERE fltipo IN ('conexao','api') AND flativo = true ORDER BY dsintegracao")->fetchAll(PDO::FETCH_ASSOC);

function iconeSeta($campo, $order, $dir) {
    if ($campo !== $order) return '';
  return $dir === 'asc' ? '▲' : '▼';
}
?>

<h4 class="mb-3"><i class="bi <?= $icone ?>"></i> <?= $titulo ?></h4>
<hr>

<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
  <div class="btn-group btn-group-sm">
    <a href="?m=integracoes&status=ativas" class="btn btn-outline-success <?= $filtro=='ativas'?'active':'' ?>">Ativas</a>
    <a href="?m=integracoes&status=inativas" class="btn btn-outline-secondary <?= $filtro=='inativas'?'active':'' ?>">Inativas</a>
    <a href="?m=integracoes&status=todas" class="btn btn-outline-dark <?= $filtro=='todas'?'active':'' ?>">Todas</a>
  </div>

  <form method="get" class="d-flex align-items-center gap-2 flex-grow-1 justify-content-center" style="max-width:420px;">
    <input type="hidden" name="m" value="integracoes">
    <input type="hidden" name="status" value="<?= $filtro ?>">
    <div class="input-group input-group-sm w-100">
      <input type="text" name="busca" class="form-control" placeholder="Pesquisar por nome ou host" value="<?= htmlspecialchars($busca) ?>">
      <button class="btn btn-outline-primary" type="submit"><i class="bi bi-search"></i></button>
    </div>
  </form>

  <button class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#modalIntegracao" id="novaIntegracaoBtn">
      <i class="bi bi-plus-circle"></i> Nova Integração
  </button>
</div>

<div class="card border-0 shadow-sm">
  <div class="table-responsive">
    <table class="table table-striped table-hover table-sm align-middle mb-0">
      <thead class="table-dark">
        <tr>
          <th><a href="?m=integracoes&order=cdintegracao&dir=<?= $nextDir ?>&status=<?= $filtro ?>" class="text-white text-decoration-none">ID <?= iconeSeta('cdintegracao', $order, $dir) ?></a></th>
          <th><a href="?m=integracoes&order=dsintegracao&dir=<?= $nextDir ?>&status=<?= $filtro ?>" class="text-white text-decoration-none">Descrição <?= iconeSeta('dsintegracao', $order, $dir) ?></a></th>
          <th>Tipo</th>
          <th>Banco/Host</th>
          <th>Empresas</th>
          <th>Schedule</th>
          <th>Status</th>
          <th class="text-end">Ações</th>
        </tr>
      </thead>
      <tbody>
        <?php if (empty($integracoes)): ?>
          <tr><td colspan="8" class="text-center py-4 text-muted">Nenhuma integração encontrada</td></tr>
        <?php else: ?>
          <?php foreach ($integracoes as $int): 
            $stmtEmps = $pdo->prepare("SELECT e.dsapelido FROM back.integracao_empresa ie JOIN back.empresa e ON e.cdempresa = ie.cdempresa WHERE ie.cdintegracao = :id");
            $stmtEmps->execute([':id' => $int['cdintegracao']]);
            $emps = $stmtEmps->fetchAll(PDO::FETCH_COLUMN);
          ?>
            <tr>
              <td><strong><?= $int['cdintegracao'] ?></strong></td>
              <td><?= htmlspecialchars($int['dsintegracao']) ?></td>
              <td>
                <?php $tipoInt = $int['fltipo'] ?? 'conexao'; ?>
                <?php if ($tipoInt === 'api'): ?>
                  <span class="badge bg-info"><i class="bi bi-cloud-arrow-up"></i> API Push</span>
                  <?php if (!empty($int['api_token_hash'])): ?>
                    <br><small class="text-success"><i class="bi bi-key-fill"></i> Token ativo</small>
                  <?php else: ?>
                    <br><small class="text-danger"><i class="bi bi-key"></i> Sem token</small>
                  <?php endif; ?>
                <?php elseif ($tipoInt === 'origem'): ?>
                  <span class="badge bg-warning text-dark"><i class="bi bi-box-arrow-in-down"></i> Origem</span>
                <?php else: ?>
                  <span class="badge bg-primary"><i class="bi bi-database"></i> Conexão</span>
                <?php endif; ?>
              </td>
              <td>
                <?php if ($tipoInt === 'api'): ?>
                  <small class="text-muted">—</small>
                <?php elseif ($tipoInt === 'origem'): ?>
                  <?php
                    $stmtConex = $pdo->prepare("SELECT i.dsintegracao FROM back.integracao_conexao ic JOIN back.integracao i ON i.cdintegracao = ic.cdintegracao_conexao WHERE ic.cdintegracao = :id");
                    $stmtConex->execute([':id' => $int['cdintegracao']]);
                    $nomesConex = $stmtConex->fetchAll(PDO::FETCH_COLUMN);
                  ?>
                  <?php if (!empty($nomesConex)): ?>
                    <small class="text-muted"><i class="bi bi-link-45deg"></i> <?= implode(', ', array_map('htmlspecialchars', $nomesConex)) ?></small>
                  <?php else: ?>
                    <small class="text-danger"><i class="bi bi-exclamation-triangle"></i> Sem conexão</small>
                  <?php endif; ?>
                <?php else: ?>
                  <span class="badge bg-secondary"><?= $tipos_banco[$int['tipo_banco']] ?? $int['tipo_banco'] ?></span>
                  <br><small class="text-muted"><?= htmlspecialchars($int['host']) ?><?= $int['porta'] ? ":{$int['porta']}" : '' ?></small>
                <?php endif; ?>
              </td>
              <td>
                <?php if ($tipoInt === 'origem'): ?>
                  <?php
                    // Herda empresas das integrações de referência
                    $stmtEmpHerda = $pdo->prepare("SELECT DISTINCT e.dsapelido FROM back.integracao_conexao ic JOIN back.integracao_empresa ie ON ie.cdintegracao = ic.cdintegracao_conexao JOIN back.empresa e ON e.cdempresa = ie.cdempresa WHERE ic.cdintegracao = :id ORDER BY e.dsapelido");
                    $stmtEmpHerda->execute([':id' => $int['cdintegracao']]);
                    $empsHerda = $stmtEmpHerda->fetchAll(PDO::FETCH_COLUMN);
                  ?>
                  <?php if (!empty($empsHerda)): ?>
                    <small class="text-muted"><i class="bi bi-arrow-return-right"></i> <?= implode(', ', array_map('htmlspecialchars', $empsHerda)) ?></small>
                  <?php else: ?>
                    <small class="text-muted">-</small>
                  <?php endif; ?>
                <?php elseif (count($emps) > 0): ?>
                  <small class="text-muted"><?= implode(', ', array_map('htmlspecialchars', $emps)) ?></small>
                <?php else: ?>
                  <small class="text-muted">-</small>
                <?php endif; ?>
              </td>
              <td>
                <?php if ($tipoInt === 'api'): ?>
                  <small class="text-muted"><i class="bi bi-cloud-arrow-up"></i> Via ERP</small>
                <?php elseif ($tipoInt === 'origem'): ?>
                  <?php
                    // Herda horários das integrações de referência
                    $stmtHorHerda = $pdo->prepare("SELECT DISTINCT ih.hora, ih.minuto FROM back.integracao_conexao ic JOIN back.integracao_horarios ih ON ih.cdintegracao = ic.cdintegracao_conexao WHERE ic.cdintegracao = :id AND ih.flativo = true ORDER BY ih.hora, ih.minuto");
                    $stmtHorHerda->execute([':id' => $int['cdintegracao']]);
                    $horasHerda = $stmtHorHerda->fetchAll(PDO::FETCH_ASSOC);
                  ?>
                  <?php if (!empty($horasHerda)): ?>
                    <span class="badge bg-success"><i class="bi bi-arrow-return-right"></i> Herda</span>
                    <br><small class="text-muted"><?= implode(', ', array_map(fn($h) => str_pad($h['hora'],2,'0',STR_PAD_LEFT).':'.str_pad($h['minuto'],2,'0',STR_PAD_LEFT), $horasHerda)) ?></small>
                    <?php if (!empty($int['ultima_sincronizacao'])): ?>
                      <br><small class="text-muted">Última: <?= date('d/m H:i', strtotime($int['ultima_sincronizacao'])) ?></small>
                    <?php endif; ?>
                  <?php else: ?>
                    <small class="text-muted">Sem horários (ref)</small>
                  <?php endif; ?>
                <?php else: ?>
                <?php
                  $autoAtivo = !empty($int['schedule_ativo']);
                  $minHoras = (int)($int['schedule_cron'] ?? 0);
                  if ($autoAtivo && $minHoras <= 0) $minHoras = 24;
                ?>
                <?php if ($autoAtivo && $minHoras > 0): ?>
                  <span class="badge bg-success"><i class="bi bi-clock-fill"></i> Auto (mín. <?= (int)$minHoras ?>h)</span>
                  <?php if (!empty($int['ultima_sincronizacao'])): ?>
                    <br><small class="text-muted">Última: <?= date('d/m H:i', strtotime($int['ultima_sincronizacao'])) ?></small>
                  <?php endif; ?>
                <?php else: ?>
                  <small class="text-muted">Manual</small>
                <?php endif; ?>
                <?php endif; ?>
              </td>
              <td>
                <?php if ($int['flativo']): ?>
                  <span class="badge bg-success">Ativa</span>
                <?php else: ?>
                  <span class="badge bg-secondary">Inativa</span>
                <?php endif; ?>
              </td>
              <td class="text-end">
                <button class="btn btn-sm btn-outline-primary edit-btn" data-id="<?= $int['cdintegracao'] ?>" data-bs-toggle="modal" data-bs-target="#modalIntegracao">
                  <i class="bi bi-pencil-square"></i>
                </button>
                <?php if (($int['fltipo'] ?? 'conexao') === 'conexao'): ?>
                <button class="btn btn-sm btn-outline-info test-btn" data-id="<?= $int['cdintegracao'] ?>" title="Testar conexão">
                  <i class="bi bi-plug"></i>
                </button>
                <?php endif; ?>
                <?php if ($int['flativo'] && ($int['fltipo'] ?? 'conexao') !== 'api'): ?>
                <button class="btn btn-sm btn-outline-warning sync-btn" data-id="<?= $int['cdintegracao'] ?>" data-tipo="<?= htmlspecialchars($int['fltipo'] ?? 'conexao') ?>" data-nome="<?= htmlspecialchars($int['dsintegracao'] ?? '') ?>" title="Sincronizar agora">
                  <i class="bi bi-arrow-repeat"></i>
                </button>
                <?php endif; ?>
                <button class="btn btn-sm btn-outline-danger delete-btn" data-id="<?= $int['cdintegracao'] ?>" title="Excluir">
                  <i class="bi bi-trash"></i>
                </button>
              </td>
            </tr>
          <?php endforeach; ?>
        <?php endif; ?>
      </tbody>
    </table>
  </div>
</div>

<div class="modal fade" id="modalIntegracao" tabindex="-1">
  <div class="modal-dialog modal-lg modal-dialog-scrollable">
    <div class="modal-content">
      <div class="modal-header bg-primary text-white py-3">
        <h5 class="modal-title"><i class="bi bi-arrow-left-right"></i> Integração de Realizado</h5>
        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body p-3">
        <form id="formIntegracao">
          <input type="hidden" id="cdintegracao" value="">
          <div class="row g-2">
            <div class="col-md-5">
              <label class="fw-bold">Nome da Integração *</label>
              <input type="text" id="dsintegracao" class="form-control" placeholder="Ex: Realizado ERP X">
            </div>
            <div class="col-md-3">
              <label class="fw-bold">Tipo de Integração *</label>
              <select id="fltipo" class="form-select">
                <option value="conexao">Conexão Direta</option>
                <option value="api">API Push</option>
                <option value="origem">Origem de Dados</option>
              </select>
            </div>
            <div class="col-md-2">
              <label class="fw-bold">Status</label>
              <div class="form-check form-switch mt-2">
                <input type="checkbox" id="flativo" class="form-check-input" checked>
                <label class="form-check-label" for="flativo">Ativa</label>
              </div>
            </div>
            <div class="col-md-2 campo-conexao" id="fieldPorta">
              <label class="fw-bold">Porta *</label>
              <input type="number" id="porta" class="form-control" value="5432">
            </div>

            <!-- CAMPOS DE CONEXÃO (apenas tipo 'conexao') -->
            <div class="col-md-4 campo-conexao" id="fieldTipoBanco">
              <label class="fw-bold">Tipo de Banco *</label>
              <select id="tipo_banco" class="form-select">
                <option value="">Selecione...</option>
                <?php foreach ($tipos_banco as $k => $v): ?>
                  <option value="<?= $k ?>"><?= $v ?></option>
                <?php endforeach; ?>
              </select>
            </div>
            <div class="col-md-5 campo-conexao" id="fieldHost">
              <label class="fw-bold">Host/IP *</label>
              <input type="text" id="host" class="form-control" placeholder="localhost ou 192.168.x.x">
            </div>
            <div class="col-md-3 campo-conexao" id="fieldSchema">
              <label class="fw-bold">Schema</label>
              <input type="text" id="schema_banco" class="form-control" value="public">
            </div>

            <div class="col-md-5 campo-conexao" id="fieldDbname">
              <label class="fw-bold">Database *</label>
              <input type="text" id="dbname" class="form-control" placeholder="nome_banco">
            </div>
            <div class="col-md-4 campo-conexao" id="fieldUsuario">
              <label class="fw-bold">Usuário *</label>
              <input type="text" id="usuario" class="form-control">
            </div>
            <div class="col-md-3 campo-conexao" id="fieldSenha">
              <label class="fw-bold">Senha <span id="senhaObrigatorio">*</span></label>
              <input type="password" id="senha" class="form-control">
              <small class="text-success fw-bold" id="senhaHint" style="display:none;">Deixe em branco para manter</small>
            </div>

            <!-- CAMPOS ORIGEM (apenas tipo 'origem') -->
            <div class="col-12 campo-origem" id="fieldConexaoRef" style="display:none;">
              <label class="fw-bold small d-block mb-1">Conexões de Referência * <small class="text-muted fw-normal">(selecione uma ou mais)</small></label>
              <div id="conexoesOrigemContainer" class="border rounded p-2" style="max-height:150px; overflow-y:auto; background:#f8f9fa;">
                <?php if (empty($integracoesFonte)): ?>
                  <small class="text-muted">Nenhuma integração de conexão/api ativa encontrada.</small>
                <?php else: ?>
                  <?php foreach ($integracoesFonte as $ic): ?>
                    <?php
                      $tipoLabel = $ic['fltipo'] === 'api' ? 'API' : ($tipos_banco[$ic['tipo_banco']] ?? $ic['tipo_banco']);
                      $hostLabel = $ic['fltipo'] === 'api' ? 'Push' : (htmlspecialchars($ic['host']) . '/' . htmlspecialchars($ic['dbname']));
                    ?>
                    <div class="form-check form-check-inline me-2">
                      <input type="checkbox" class="form-check-input conexao-origem-checkbox" id="conex_<?= $ic['cdintegracao'] ?>" value="<?= $ic['cdintegracao'] ?>">
                      <label class="form-check-label small" for="conex_<?= $ic['cdintegracao'] ?>"><?= htmlspecialchars($ic['dsintegracao']) ?> <span class="badge bg-secondary"><?= $tipoLabel ?></span> <small class="text-muted"><?= $hostLabel ?></small></label>
                    </div>
                  <?php endforeach; ?>
                <?php endif; ?>
              </div>
              <small class="text-muted"><i class="bi bi-info-circle"></i> A integração "origem" usará as conexões de banco selecionadas para buscar os dados.</small>
            </div>
            <div class="col-md-6 campo-origem" id="fieldCampoEmpresa" style="display:none;">
              <label class="fw-bold">Campo Empresa *</label>
              <input type="text" id="campo_empresa" class="form-control" placeholder="Ex: IDSERIE, CDEMPRESA">
              <small class="text-muted">Coluna do SELECT cujo valor corresponde ao <code>back.empresa.cdintegracao</code> (código da empresa no ERP)</small>
            </div>

            <!-- TOKEN API (apenas tipo 'api') -->
            <div class="col-12 campo-api" id="sectionToken" style="display:none;">
              <div class="card border-info">
                <div class="card-header bg-info text-white py-2">
                  <small><i class="bi bi-key"></i> <strong>Token de Autenticação API</strong></small>
                </div>
                <div class="card-body p-3">
                  <div id="tokenStatus">
                    <div class="text-muted small mb-2">
                      <i class="bi bi-info-circle"></i> O token é necessário para que o script do ERP se autentique com o Napoleon. 
                      Ele é exibido <strong>apenas uma vez</strong> após ser gerado — copie e guarde com segurança.
                    </div>
                  </div>
                  <div id="tokenGerado" style="display:none;">
                    <div class="alert alert-success mb-2 py-2">
                      <i class="bi bi-check-circle"></i> Token gerado! Copie agora — <strong>não será exibido novamente</strong>.
                    </div>
                    <div class="input-group">
                      <input type="text" id="tokenPlaintext" class="form-control font-monospace" readonly style="font-size:0.85rem;">
                      <button type="button" class="btn btn-outline-primary" id="btnCopiarToken" title="Copiar token">
                        <i class="bi bi-clipboard"></i> Copiar
                      </button>
                    </div>
                  </div>
                  <div id="tokenExistente" style="display:none;">
                    <div class="alert alert-secondary mb-2 py-2">
                      <i class="bi bi-shield-lock"></i> Token já configurado. Para gerar um novo (invalida o anterior):
                    </div>
                  </div>
                  <div id="tokenNenhum" style="display:none;">
                    <div class="alert alert-warning mb-2 py-2">
                      <i class="bi bi-exclamation-triangle"></i> Nenhum token configurado. Gere um token para ativar a API.
                    </div>
                  </div>
                  <button type="button" class="btn btn-sm btn-outline-info mt-1" id="btnGerarToken" style="display:none;">
                    <i class="bi bi-arrow-repeat"></i> Gerar Novo Token
                  </button>
                  <div id="tokenStatusMsg" class="small mt-2"></div>
                </div>
              </div>
            </div>

            <div class="col-12">
              <label class="fw-bold">SQL de Origem *</label>
              <textarea id="sql_origem" class="form-control font-monospace" rows="7" placeholder="SELECT cdorigem, cdempresa, cdcentrocusto, cdplanocontabil, dtmovimento, tpmovimento, valor, dscomplemento FROM ..."></textarea>
              <div class="alert alert-light border border-warning mt-2 mb-2 p-2" id="sqlHintRealizado">
                <small class="text-muted">
                  <strong>Campos obrigatórios:</strong> cdorigem (código de origem do lançamento no ERP, gravado em back.realizado.cdorigem), cdempresa (Codigo Serial entre Helm X ERP), cdcentrocusto, cdplanocontabil, dtmovimento (auto-resolve ano/mês), tpmovimento (D/C), valor, dscomplemento
                </small>
              </div>
              <div class="alert alert-light border border-info mt-2 mb-2 p-2" id="sqlHintOrigem" style="display:none;">
                <small class="text-muted">
                  <i class="bi bi-info-circle"></i> <strong>O SELECT deve retornar exatamente 2 colunas:</strong> a coluna empresa (informada no campo acima) + 1 coluna de valor. O valor será armazenado na coluna <code>back.origem_dados.valor</code> para uso em variáveis.
                </small>
              </div>
              <button type="button" class="btn btn-sm btn-outline-info" id="btnVerificarDados"><i class="bi bi-eye"></i> Verificar dados</button>
              <div id="sqlErroOrigem" class="text-danger small mt-1" style="display:none;"></div>
            </div>

            <div class="col-12" id="verificarDadosSection"></div>

            <div class="col-12 campo-empresas-horarios">
              <label class="fw-bold small d-block mb-1">Empresas vinculadas</label>
              <div id="empresasContainer" class="border rounded p-2" style="max-height:120px; overflow-y:auto; background:#f8f9fa;">
                <?php foreach ($empresas as $emp): ?>
                  <div class="form-check form-check-inline me-2">
                    <input type="checkbox" class="form-check-input empresa-checkbox" id="emp_<?= $emp['cdempresa'] ?>" value="<?= $emp['cdempresa'] ?>">
                    <label class="form-check-label small" for="emp_<?= $emp['cdempresa'] ?>"><?= htmlspecialchars($emp['dsapelido']) ?></label>
                  </div>
                <?php endforeach; ?>
              </div>
            </div>

            <div class="col-12 campo-origem" id="infoHerdaEmpresasHorarios" style="display:none;">
              <div class="alert alert-info mb-0 py-2 small">
                <i class="bi bi-info-circle"></i> <strong>Empresas</strong> e <strong>Horários</strong> são herdados automaticamente das integrações de referência selecionadas acima.
              </div>
            </div>

            <div class="col-12 campo-empresas-horarios" id="sectionHorarios">
              <div class="card border-primary border-1">
                <div class="card-header bg-primary text-white py-2 d-flex justify-content-between align-items-center">
                  <small><i class="bi bi-clock"></i> <strong>Horários Agendados</strong></small>
                  <button type="button" class="btn btn-sm btn-light" id="btnAdicionarHorario" title="Adicionar novo horário">
                    <i class="bi bi-plus-circle"></i>
                  </button>
                </div>
                <div class="card-body p-2">
                  <small class="text-muted d-block mb-2">
                    <i class="bi bi-info-circle"></i> Configure múltiplos horários para sincronização automática (ex: 08:00, 14:00, 20:00)
                  </small>
                  <div id="horariosContainer">
                    <div class="alert alert-light border border-dashed text-center text-muted py-2" style="font-size:0.9rem;">
                      Nenhum horário configurado. Clique em <strong>+</strong> para adicionar.
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div class="col-12" id="testeResultadoInline"></div>
          </div>
        </form>
      </div>
      <div class="modal-footer py-2 d-flex justify-content-between align-items-center gap-2">
        <button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Fechar</button>
        <div class="d-flex gap-2">
          <button type="button" class="btn btn-sm btn-outline-info campo-conexao" id="btnTestarConexaoInline"><i class="bi bi-plug"></i> Testar</button>
          <button type="button" class="btn btn-primary" id="btnSalvarIntegracao"><i class="bi bi-check-lg"></i> Salvar</button>
        </div>
      </div>
    </div>
  </div>
</div>

<div class="modal fade" id="modalTesteConexao" tabindex="-1">
  <div class="modal-dialog modal-md modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header bg-info text-white py-2">
        <h6 class="modal-title"><i class="bi bi-plug"></i> Teste de Conexão</h6>
        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body"><div id="testeResultado">Testando...</div></div>
      <div class="modal-footer py-2">
        <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Fechar</button>
      </div>
    </div>
  </div>
</div>

<!-- Modal Sincronização Manual -->
<div class="modal fade" id="modalSync" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
  <div class="modal-dialog modal-md modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header bg-warning py-2">
        <h6 class="modal-title"><i class="bi bi-arrow-repeat"></i> Sincronização Manual</h6>
        <button type="button" class="btn-close" data-bs-dismiss="modal" id="btnFecharSync"></button>
      </div>
      <div class="modal-body">
        <div id="syncNomeIntegracao" class="fw-bold mb-2"></div>
        <div id="syncProgresso">
          <ul class="list-unstyled small mb-2" id="syncEtapas">
            <li id="syncEtapa1" class="text-muted"><i class="bi bi-hourglass"></i> 1) Sincronizando dados da integração...</li>
            <li id="syncEtapa2" class="text-muted" style="display:none;"><i class="bi bi-hourglass"></i> 2) Consolidando views materializadas...</li>
            <li id="syncEtapa3" class="text-muted" style="display:none;"><i class="bi bi-hourglass"></i> 3) Atualizando origens vinculadas...</li>
          </ul>
          <div class="progress mb-2" style="height: 6px;">
            <div class="progress-bar progress-bar-striped progress-bar-animated bg-warning" role="progressbar" id="syncProgressBar" style="width: 10%;"></div>
          </div>
        </div>
        <div id="syncResultado" class="small"></div>
      </div>
      <div class="modal-footer py-2">
        <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Fechar</button>
      </div>
    </div>
  </div>
</div>

<style>
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.spin-icon { animation: spin 1s linear infinite; display: inline-block; }
</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

<script>
function escapeHtml(text) {
  const d = document.createElement('div');
  d.appendChild(document.createTextNode(text));
  return d.innerHTML;
}

const modalIntegracao = new bootstrap.Modal(document.getElementById('modalIntegracao'));
const modalTesteConexao = new bootstrap.Modal(document.getElementById('modalTesteConexao'));

// ===== Tipo de integração: visibilidade condicional =====
function atualizarVisibilidadeTipo() {
  const tipo = $('#fltipo').val();
  const isApi = (tipo === 'api');
  const isOrigem = (tipo === 'origem');
  const isConexao = (tipo === 'conexao');
  const hasId = !!$('#cdintegracao').val();
  
  // Campos de conexão (DB fields + testar): só para "conexao"
  $('.campo-conexao').toggle(isConexao);
  // Campos exclusivos API (token)
  $('.campo-api').toggle(isApi);
  // Campos exclusivos Origem (conexão referência + campo chave)
  $('.campo-origem').toggle(isOrigem);
  // Empresas e horários: NÃO mostrar para origem (herda das integrações de referência)
  $('.campo-empresas-horarios').toggle(!isOrigem);
  $('#infoHerdaEmpresasHorarios').toggle(isOrigem);
  
  // Botão verificar dados: conexao e origem (não API)
  $('#btnVerificarDados').toggle(isConexao || isOrigem);
  // Dica SQL: realizado (conexao/api) vs origem
  $('#sqlHintRealizado').toggle(isConexao || isApi);
  $('#sqlHintOrigem').toggle(isOrigem);
  
  // Botão gerar token: só se já salvou (tem ID) e tipo api
  $('#btnGerarToken').toggle(isApi && hasId);
  // Se API mas sem ID, mostra mensagem
  if (isApi && !hasId) {
    $('#tokenNenhum').hide();
    $('#tokenStatusMsg').html('<i class="bi bi-info-circle text-muted"></i> Salve a integração primeiro para gerar o token.');
  }
  
  // Atualizar required nos campos de conexão
  if (isApi || isOrigem) {
    $('#tipo_banco, #host, #porta, #dbname, #usuario').removeAttr('required');
  } else {
    $('#tipo_banco, #host, #porta, #dbname, #usuario').attr('required', 'required');
  }
}

$('#fltipo').on('change', atualizarVisibilidadeTipo);

// ===== Token API =====
$('#btnGerarToken').on('click', async function() {
  const id = $('#cdintegracao').val();
  if (!id) {
    alert('Salve a integração primeiro para gerar o token.');
    return;
  }
  
  const hasToken = $('#tokenExistente').is(':visible');
  if (hasToken) {
    if (!confirm('⚠️ Ao gerar um novo token, o token anterior será INVALIDADO.\nO script push no ERP precisará ser atualizado.\n\nDeseja continuar?')) return;
  }
  
  $(this).prop('disabled', true).html('<i class="bi bi-hourglass-split"></i> Gerando...');
  
  try {
    const resp = await fetch(`?m=integracoes_actions&ajax=gerar_token&cdintegracao=${id}`, {
      method: 'POST'
    }).then(r => r.json());
    
    if (resp.ok) {
      $('#tokenPlaintext').val(resp.token);
      $('#tokenGerado').show();
      $('#tokenExistente').hide();
      $('#tokenNenhum').hide();
      $('#tokenStatusMsg').html('<i class="bi bi-exclamation-triangle text-warning"></i> <strong>Copie agora!</strong> Este token não será exibido novamente.');
    } else {
      alert('Erro ao gerar token: ' + resp.msg);
    }
  } catch(e) {
    alert('Erro de comunicação: ' + e.message);
  } finally {
    $(this).prop('disabled', false).html('<i class="bi bi-key"></i> Gerar Token');
  }
});

$('#btnCopiarToken').on('click', function() {
  const token = $('#tokenPlaintext').val();
  if (!token) return;
  
  navigator.clipboard.writeText(token).then(() => {
    const btn = $(this);
    btn.html('<i class="bi bi-check-lg"></i> Copiado!').removeClass('btn-outline-primary').addClass('btn-success');
    setTimeout(() => btn.html('<i class="bi bi-clipboard"></i> Copiar').removeClass('btn-success').addClass('btn-outline-primary'), 2000);
  }).catch(() => {
    // Fallback para navegadores sem Clipboard API
    $('#tokenPlaintext').select();
    document.execCommand('copy');
    alert('Token copiado!');
  });
});

function validarSQLOrigem(sql) {
  if (!sql) return false;
  const sqlTrim = sql.trim();
  if (!sqlTrim) return false;
  if (sqlTrim.includes(';')) return false;
  if (!/^\s*(SELECT|WITH)\b/i.test(sqlTrim)) return false;
  const bloqueados = ['INSERT','UPDATE','DELETE','MERGE','TRUNCATE','DROP','ALTER','CREATE','GRANT','REVOKE','COMMENT','EXEC','EXECUTE','CALL'];
  for (const cmd of bloqueados) {
    if (new RegExp('\\b' + cmd + '\\b', 'i').test(sqlTrim)) return false;
  }
  return true;
}

$('#sql_origem').on('input', function() {
  const sql = $(this).val();
  const erro = $('#sqlErroOrigem');
  if (!validarSQLOrigem(sql)) {
    erro.html('❌ <strong>SQL inválido:</strong> Apenas SELECT são aceitos. Instruções INSERT, UPDATE, DELETE, DROP, ALTER são bloqueadas por segurança.').show();
    $(this).addClass('is-invalid');
  } else {
    erro.hide();
    $(this).removeClass('is-invalid');
  }
});

function resetForm() {
  $('#formIntegracao')[0].reset();
  $('#cdintegracao').val('');
  $('#fltipo').val('conexao');
  $('#schema_banco').val('public');
  $('#flativo').prop('checked', true);
  $('#testeResultadoInline').html('');
  $('.empresa-checkbox').prop('checked', false);
  $('#senhaObrigatorio').show();
  $('#senhaHint').hide();
  // Reset token section
  $('#tokenGerado').hide();
  $('#tokenExistente').hide();
  $('#tokenNenhum').show();
  $('#tokenPlaintext').val('');
  $('#tokenStatusMsg').html('');
  // Reset campos origem
  $('.conexao-origem-checkbox').prop('checked', false);
  $('#campo_empresa').val('');
  // Reset horários
  $('#horariosContainer').html('<div class="alert alert-light border border-dashed text-center text-muted py-2" style="font-size:0.9rem;">Nenhum horário configurado. Clique em <strong>+</strong> para adicionar.</div>');
  // Atualizar visibilidade pelo tipo
  atualizarVisibilidadeTipo();
}

// Armazena horários temporários durante edição
let horariosTemp = [];

function renderizarHorarios() {
  const container = $('#horariosContainer');
  
  if (horariosTemp.length === 0) {
    container.html('<div class="alert alert-light border border-dashed text-center text-muted py-2" style="font-size:0.9rem;">Nenhum horário configurado. Clique em <strong>+</strong> para adicionar.</div>');
    return;
  }
  
  let html = '<div class="row g-2">';
  horariosTemp.forEach((horario, idx) => {
    const hora = String(horario.hora).padStart(2, '0');
    const minuto = String(horario.minuto).padStart(2, '0');
    const statusClass = horario.flativo ? 'bg-success' : 'bg-secondary';
    html += `
      <div class="col-md-3">
        <div class="card border-${horario.flativo ? 'success' : 'secondary'} h-100">
          <div class="card-body p-2 text-center">
            <div class="fw-bold" style="font-size:1.5rem;">${hora}:${minuto}</div>
            <div class="form-check form-check-inline mt-1 mb-2">
              <input type="checkbox" class="form-check-input" id="hor_ativo_${idx}" 
                ${horario.flativo ? 'checked' : ''} 
                onchange="horariosTemp[${idx}].flativo = this.checked; renderizarHorarios();">
              <label class="form-check-label small" for="hor_ativo_${idx}">Ativo</label>
            </div>
            <button type="button" class="btn btn-sm btn-outline-danger w-100" onclick="removerHorario(${idx})">
              <i class="bi bi-trash"></i> Remover
            </button>
          </div>
        </div>
      </div>
    `;
  });
  html += '</div>';
  container.html(html);
}

function removerHorario(idx) {
  horariosTemp.splice(idx, 1);
  renderizarHorarios();
}

$('#btnAdicionarHorario').on('click', () => {
  // Abre um pequeno modal para inserir hora/minuto
  const hora = prompt('Digite a hora (0-23):', '08');
  if (hora === null) return;
  const horaParse = parseInt(hora, 10);
  if (isNaN(horaParse) || horaParse < 0 || horaParse > 23) {
    alert('Hora inválida (0-23)');
    return;
  }
  
  const minuto = prompt('Digite o minuto (0-59):', '00');
  if (minuto === null) return;
  const minutoParse = parseInt(minuto, 10);
  if (isNaN(minutoParse) || minutoParse < 0 || minutoParse > 59) {
    alert('Minuto inválido (0-59)');
    return;
  }
  
  // Verifica duplicatas
  const existe = horariosTemp.some(h => h.hora === horaParse && h.minuto === minutoParse);
  if (existe) {
    alert(`Horário ${String(horaParse).padStart(2, '0')}:${String(minutoParse).padStart(2, '0')} já existe`);
    return;
  }
  
  horariosTemp.push({ 
    cdhorario: null, 
    hora: horaParse, 
    minuto: minutoParse, 
    flativo: true 
  });
  renderizarHorarios();
});

$('#novaIntegracaoBtn').on('click', () => {
  resetForm();
  horariosTemp = [];
});

$(document).on('click', '.edit-btn', async function() {
  resetForm();
  const id = $(this).data('id');
  console.log('Buscando integração ID:', id);
  
  try {
    const response = await fetch(`?m=integracoes_actions&ajax=obter&cdintegracao=${id}`);
    const text = await response.text();
    console.log('Resposta raw:', text);
    
    let resp;
    try {
      resp = JSON.parse(text);
    } catch(e) {
      alert('Erro no servidor. Verifique o console para detalhes.');
      console.error('Resposta não é JSON:', text);
      return;
    }
    
    console.log('Resposta do servidor:', resp);
    
    if (!resp.ok) { 
      alert(resp.msg); 
      return; 
    }
    
    const d = resp.data;
    console.log('Dados recebidos:', d);
    
    $('#cdintegracao').val(d.cdintegracao);
    $('#dsintegracao').val(d.dsintegracao);
    $('#fltipo').val(d.fltipo || 'conexao');
    $('#flativo').prop('checked', !!d.flativo);
    $('#tipo_banco').val(d.tipo_banco);
    $('#host').val(d.host);
    $('#porta').val(d.porta || 5432);
    $('#schema_banco').val(d.schema_banco || 'public');
    $('#dbname').val(d.dbname);
    $('#usuario').val(d.usuario);
    $('#sql_origem').val(d.sql_origem || '');
    $('.empresa-checkbox').prop('checked', false);
    (d.empresas || []).forEach(cd => $(`#emp_${cd}`).prop('checked', true));
    $('#senha').val('');
    $('#senhaObrigatorio').hide();
    $('#senhaHint').show();
    
    // Campos de origem
    $('.conexao-origem-checkbox').prop('checked', false);
    (d.conexoes_origem || []).forEach(cd => $(`#conex_${cd}`).prop('checked', true));
    $('#campo_empresa').val(d.campo_empresa || '');
    
    // Token status
    $('#tokenGerado').hide();
    $('#tokenPlaintext').val('');
    $('#tokenStatusMsg').html('');
    if (d.has_token) {
      $('#tokenExistente').show();
      $('#tokenNenhum').hide();
    } else {
      $('#tokenExistente').hide();
      $('#tokenNenhum').show();
    }
    
    // Atualizar visibilidade pelo tipo
    atualizarVisibilidadeTipo();
    
    // Carregar horários agendados
    horariosTemp = d.horarios || [];
    renderizarHorarios();
    
    console.log('Campos preenchidos com sucesso');
  } catch(e) {
    console.error('Erro ao carregar integração:', e);
    alert('Erro ao carregar dados: ' + e.message);
  }
});

$('#btnSalvarIntegracao').on('click', async () => {
  const id = $('#cdintegracao').val();
  const fltipo = $('#fltipo').val();
  const isApi = (fltipo === 'api');
  const isOrigem = (fltipo === 'origem');
  
  const dados = {
    fltipo: fltipo,
    dsintegracao: $('#dsintegracao').val(),
    flativo: $('#flativo').is(':checked') ? 1 : 0,
    tipo_banco: (isApi || isOrigem) ? '' : $('#tipo_banco').val(),
    host: (isApi || isOrigem) ? '' : $('#host').val(),
    porta: (isApi || isOrigem) ? '' : $('#porta').val(),
    schema_banco: (isApi || isOrigem) ? '' : ($('#schema_banco').val() || 'public'),
    dbname: (isApi || isOrigem) ? '' : $('#dbname').val(),
    usuario: (isApi || isOrigem) ? '' : $('#usuario').val(),
    senha: (isApi || isOrigem) ? '' : $('#senha').val(),
    sql_origem: $('#sql_origem').val(),
    empresas: isOrigem ? [] : $('.empresa-checkbox:checked').map(function() { return $(this).val(); }).get(),
    horarios: (isApi || isOrigem) ? [] : horariosTemp.map(h => ({ hora: h.hora, minuto: h.minuto, flativo: h.flativo })),
    conexoes_origem: isOrigem ? $('.conexao-origem-checkbox:checked').map(function() { return $(this).val(); }).get() : [],
    campo_empresa: isOrigem ? $('#campo_empresa').val() : ''
  };

  // Validação condicional
  if (!dados.dsintegracao) { alert('Preencha o nome da integração'); return; }
  if (isOrigem) {
    if (!dados.conexoes_origem || dados.conexoes_origem.length === 0) { alert('Selecione ao menos uma conexão de referência'); return; }
    if (!dados.campo_empresa) { alert('Preencha o campo empresa (coluna que relaciona com back.empresa)'); return; }
    if (!dados.sql_origem) { alert('Preencha o SQL de origem'); return; }
    // Validar que SQL retorna exatamente 2 colunas
    const sqlUpper = dados.sql_origem.toUpperCase();
    const matchSelect = sqlUpper.match(/\bSELECT\b([\s\S]*?)\bFROM\b/);
    if (matchSelect) {
      const selectPart = matchSelect[1];
      let nivel = 0, ncols = 1;
      for (let i = 0; i < selectPart.length; i++) {
        if (selectPart[i] === '(') nivel++;
        else if (selectPart[i] === ')') nivel--;
        else if (selectPart[i] === ',' && nivel === 0) ncols++;
      }
      if (ncols !== 2) {
        alert(`O SELECT de uma integração "origem" deve retornar exatamente 2 colunas (campo empresa + 1 coluna de valor).\nForam detectadas ${ncols} colunas.`);
        return;
      }
    }
  } else if (!isApi) {
    const obrig = [dados.tipo_banco, dados.host, dados.porta, dados.dbname, dados.usuario, dados.sql_origem];
    if (obrig.some(v => !v)) { alert('Preencha os campos obrigatórios de conexão'); return; }
    if (!id && !dados.senha) { alert('Senha é obrigatória na criação'); return; }
  } else {
    if (!dados.sql_origem) { alert('Preencha o SQL de origem'); return; }
  }
  if (dados.sql_origem && !validarSQLOrigem(dados.sql_origem)) { alert('❌ SQL inválido: Apenas SELECT/CTE são aceitos.\nProibido: INSERT, UPDATE, DELETE, DROP, ALTER, etc.'); return; }

  const url = id ? `?m=integracoes_actions&ajax=editar&cdintegracao=${id}` : '?m=integracoes_actions&ajax=criar';
  const resp = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(dados)
  }).then(r => r.json());

  alert(resp.msg);
  if (resp.ok) {
    modalIntegracao.hide();
    setTimeout(() => location.reload(), 300);
  }
});

$('#btnVerificarDados').on('click', async () => {
  const id = $('#cdintegracao').val();
  const sql = $('#sql_origem').val();
  const fltipo = $('#fltipo').val();
  
  if (!id) {
    alert('Salve a integração primeiro');
    return;
  }
  
  if (!sql) {
    alert('Preencha o SQL de origem');
    return;
  }
  
  $('#verificarDadosSection').html('<div class="alert alert-info py-2 small"><i class="bi bi-hourglass-split"></i> Carregando última linha...</div>');
  
  const resp = await fetch(`?m=integracoes_actions&ajax=verificar_dados&cdintegracao=${id}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ sql_origem: sql })
  }).then(r => r.json());
  
  if (resp.ok) {
    let html = '<div class="card border-info mt-2"><div class="card-header bg-info text-white py-2 small"><i class="bi bi-table"></i> Último registro da origem</div><div class="card-body p-2">';
    
    if (resp.data && Object.keys(resp.data).length > 0) {
      html += '<table class="table table-sm table-bordered mb-0"><tbody>';
      for (const [chave, valor] of Object.entries(resp.data)) {
        const displayVal = valor === null ? '<em class="text-muted">NULL</em>' : (typeof valor === 'object' ? JSON.stringify(valor) : String(valor).substring(0, 100));
        html += `<tr><td class="fw-bold small" style="width:200px;">${chave}</td><td class="small">${displayVal}</td></tr>`;
      }
      html += '</tbody></table>';
    } else {
      html += '<div class="text-muted small">Nenhum registro encontrado</div>';
    }
    
    html += '</div></div>';
    $('#verificarDadosSection').html(html);
  } else {
    $('#verificarDadosSection').html(`<div class="alert alert-danger py-2 small"><i class="bi bi-x-circle"></i> ${resp.msg}</div>`);
  }
});

$('#btnTestarConexaoInline').on('click', async () => {
  const dados = {
    tipo_banco: $('#tipo_banco').val(),
    host: $('#host').val(),
    porta: $('#porta').val(),
    dbname: $('#dbname').val(),
    usuario: $('#usuario').val(),
    senha: $('#senha').val()
  };

  if (!dados.tipo_banco || !dados.host || !dados.dbname || !dados.usuario) {
    $('#testeResultadoInline').html('<div class="alert alert-warning py-1 small">Preencha os dados de conexão</div>');
    return;
  }

  $('#testeResultadoInline').html('<div class="alert alert-info py-1 small"><i class="bi bi-hourglass-split"></i> Testando...</div>');
  const resp = await fetch('?m=integracoes_actions&ajax=testar_temp', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(dados)
  }).then(r => r.json());

  if (resp.ok) {
    $('#testeResultadoInline').html(`<div class="alert alert-success py-1 small"><i class="bi bi-check-circle"></i> ${resp.msg}</div>`);
  } else {
    $('#testeResultadoInline').html(`<div class="alert alert-danger py-1 small"><i class="bi bi-x-circle"></i> ${resp.msg}</div>`);
  }
});

$(document).on('click', '.test-btn', async function() {
  const id = $(this).data('id');
  modalTesteConexao.show();
  $('#testeResultado').html('<div class="text-center"><i class="bi bi-hourglass-split"></i> Testando...</div>');
  const resp = await fetch(`?m=integracoes_actions&ajax=testar&cdintegracao=${id}`).then(r => r.json());
  if (resp.ok) {
    $('#testeResultado').html(`<div class="alert alert-success mb-0"><i class="bi bi-check-circle"></i> ${resp.msg}</div>`);
  } else {
    $('#testeResultado').html(`<div class="alert alert-danger mb-0"><i class="bi bi-x-circle"></i> ${resp.msg}</div>`);
  }
});

$(document).on('click', '.delete-btn', async function() {
  if (!confirm('Excluir esta integração?')) return;
  const id = $(this).data('id');
  const resp = await fetch(`?m=integracoes_actions&ajax=deletar&cdintegracao=${id}`, { method: 'POST' }).then(r => r.json());
  alert(resp.msg);
  if (resp.ok) setTimeout(() => location.reload(), 300);
});

// ===== Sincronização Manual =====
let modalSync = new bootstrap.Modal(document.getElementById('modalSync'));

function setSyncEtapa(etapa, status = 'running') {
  const el = $(`#syncEtapa${etapa}`);
  el.show();
  if (status === 'running') {
    el.removeClass('text-muted text-success text-danger').addClass('text-warning');
    el.find('i').attr('class', 'bi bi-arrow-repeat spin-icon');
  } else if (status === 'ok') {
    el.removeClass('text-muted text-warning text-danger').addClass('text-success');
    el.find('i').attr('class', 'bi bi-check-circle-fill');
  } else if (status === 'error') {
    el.removeClass('text-muted text-warning text-success').addClass('text-danger');
    el.find('i').attr('class', 'bi bi-x-circle-fill');
  }
}

$(document).on('click', '.sync-btn', async function() {
  const id = $(this).data('id');
  const tipo = $(this).data('tipo');
  const nome = $(this).data('nome') || `Integração #${id}`;
  const btn = $(this);

  // Desabilitar botão
  btn.prop('disabled', true).find('i').addClass('spin-icon');

  // Reset modal
  $('#syncNomeIntegracao').text(nome);
  ['#syncEtapa1','#syncEtapa2','#syncEtapa3'].forEach(s => {
    $(s).removeClass('text-success text-warning text-danger').addClass('text-muted').find('i').attr('class', 'bi bi-hourglass');
  });
  $('#syncEtapa2, #syncEtapa3').hide();
  $('#syncProgressBar').css('width', '10%');
  $('#syncResultado').html('');

  const isOrigem = (tipo === 'origem');
  const endpoint = isOrigem ? 'sincronizar_origem' : 'sincronizar_agora';

  // Ajustar labels das etapas conforme tipo
  if (isOrigem) {
    $('#syncEtapa1').html('<i class="bi bi-hourglass"></i> 1) Sincronizando dados de origem...');
    $('#syncEtapa2').hide();
    $('#syncEtapa3').hide();
  } else {
    $('#syncEtapa1').html('<i class="bi bi-hourglass"></i> 1) Sincronizando dados da integração...');
    $('#syncEtapa2').html('<i class="bi bi-hourglass"></i> 2) Consolidando views materializadas...').hide();
    $('#syncEtapa3').html('<i class="bi bi-hourglass"></i> 3) Atualizando origens vinculadas...').hide();
  }

  modalSync.show();
  setSyncEtapa(1, 'running');

  try {
    const resp = await fetch(`?m=integracoes_actions&ajax=${endpoint}&cdintegracao=${id}`);
    let json;
    try {
      const text = await resp.text();
      json = JSON.parse(text);
    } catch(pe) {
      setSyncEtapa(1, 'error');
      $('#syncResultado').html(`<div class="alert alert-danger py-2 small">Erro ao processar resposta do servidor</div>`);
      return;
    }

    if (!json.ok) {
      setSyncEtapa(1, 'error');
      $('#syncProgressBar').css('width', '100%').removeClass('bg-warning').addClass('bg-danger');
      $('#syncResultado').html(`<div class="alert alert-warning py-2 small">${escapeHtml(json.msg || 'Erro na sincronização')}</div>`);
      return;
    }

    setSyncEtapa(1, 'ok');
    $('#syncProgressBar').css('width', '50%');

    // Etapa consolidação (não-origem)
    if (!isOrigem && json.consolidacao) {
      $('#syncEtapa2').show();
      setSyncEtapa(2, json.consolidacao.ok ? 'ok' : 'error');
      $('#syncProgressBar').css('width', '75%');
    }

    // Etapa cascading origens
    if (!isOrigem && json.cascade_origens && json.cascade_origens.length > 0) {
      $('#syncEtapa3').show();
      const allOk = json.cascade_origens.every(o => o.ok);
      setSyncEtapa(3, allOk ? 'ok' : 'error');
    }

    $('#syncProgressBar').css('width', '100%').removeClass('bg-warning').addClass('bg-success');

    // Montar resultado
    let html = `<div class="alert alert-success py-2 small mb-2"><i class="bi bi-check-circle"></i> ${escapeHtml(json.msg || 'Sincronização concluída').replace(/\n/g, '<br>')}</div>`;

    // Detalhes totais
    html += `<div class="alert alert-info py-2 small mb-2">
      <strong>Totais:</strong> ${json.total || 0} inseridos | ${json.ignorados || 0} ignorados | ${json.erros || 0} erros
    </div>`;

    // Cascading details
    if (json.cascade_origens && json.cascade_origens.length > 0) {
      html += `<div class="alert alert-secondary py-2 small mb-0">
        <strong><i class="bi bi-link-45deg"></i> Origens vinculadas (${json.cascade_origens.length}):</strong><br>`;
      json.cascade_origens.forEach(o => {
        const icon = o.ok ? '<i class="bi bi-check-circle text-success"></i>' : '<i class="bi bi-x-circle text-danger"></i>';
        html += `${icon} ${escapeHtml(o.dsintegracao || 'Origem #' + o.cdintegracao)}`;
        if (o.ok) {
          html += `: ${o.total || 0} registros`;
          if (o.ignorados > 0) html += ` (${o.ignorados} ignorados)`;
        } else {
          html += `: ${escapeHtml(o.msg || 'Erro')}`;
        }
        html += '<br>';
      });
      html += `</div>`;
    }

    $('#syncResultado').html(html);

  } catch(e) {
    setSyncEtapa(1, 'error');
    $('#syncProgressBar').css('width', '100%').removeClass('bg-warning').addClass('bg-danger');
    $('#syncResultado').html(`<div class="alert alert-danger py-2 small">${e.message || 'Erro inesperado'}</div>`);
  } finally {
    btn.prop('disabled', false).find('i').removeClass('spin-icon');
  }
});

// O controle de "mínimo de horas" é salvo diretamente (0 = manual)
</script>
