Files
wevads-platform/scripts/brain-dashboard.php
2026-02-26 04:53:11 +01:00

568 lines
41 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
ini_set("memory_limit", "512M");
/**
* BRAIN ENGINE DASHBOARD - ULTRA DETAILED DRILL-DOWN
*/
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Handle POST actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'add_config') {
$stmt = $pdo->prepare("INSERT INTO admin.brain_configs (isp_target, send_method, domain_used, from_email, subject_template, source, notes) VALUES (?, ?, ?, ?, ?, 'manual', ?)");
$stmt->execute([$_POST['isp_target'], $_POST['send_method'], $_POST['domain_used'], $_POST['from_email'] ?? '', $_POST['subject_template'] ?? '', $_POST['notes'] ?? '']);
$success = "Config ajoutée !";
} elseif ($action === 'mark_inbox') {
$id = (int)$_POST['config_id'];
$pdo->exec("UPDATE admin.brain_configs SET inbox_count = inbox_count + 1, total_sent = total_sent + 1, inbox_rate = CASE WHEN total_sent > 0 THEN (inbox_count::decimal / total_sent) * 100 ELSE 0 END, consecutive_inbox = consecutive_inbox + 1, consecutive_spam = 0, confidence_score = LEAST(100, confidence_score + 5), last_success_at = NOW(), updated_at = NOW() WHERE id = $id");
$check = $pdo->query("SELECT inbox_rate, total_sent, is_winner FROM admin.brain_configs WHERE id = $id")->fetch();
if ($check['inbox_rate'] >= 80 && $check['total_sent'] >= 10 && !$check['is_winner']) {
$pdo->exec("UPDATE admin.brain_configs SET is_winner = true WHERE id = $id");
}
$success = "Marqué INBOX ✅";
} elseif ($action === 'mark_spam') {
$id = (int)$_POST['config_id'];
$pdo->exec("UPDATE admin.brain_configs SET spam_count = spam_count + 1, total_sent = total_sent + 1, inbox_rate = CASE WHEN total_sent > 0 THEN (inbox_count::decimal / total_sent) * 100 ELSE 0 END, consecutive_spam = consecutive_spam + 1, consecutive_inbox = 0, confidence_score = GREATEST(0, confidence_score - 10), updated_at = NOW() WHERE id = $id");
$success = "Marqué SPAM 📛";
}
}
$configs = $pdo->query("SELECT * FROM admin.brain_configs ORDER BY inbox_rate DESC, confidence_score DESC LIMIT 100")->fetchAll(PDO::FETCH_ASSOC);
$winners = $pdo->query("SELECT c.* FROM admin.brain_configs c WHERE c.is_winner = true ORDER BY c.inbox_rate DESC")->fetchAll(PDO::FETCH_ASSOC);
$seeds = $pdo->query("SELECT * FROM admin.brain_seeds ORDER BY is_active DESC, isp LIMIT 50")->fetchAll(PDO::FETCH_ASSOC);
$stats = $pdo->query("SELECT COUNT(*) as total_configs, COUNT(CASE WHEN is_winner THEN 1 END) as total_winners, SUM(total_sent) as total_tests, AVG(inbox_rate) as avg_rate, MAX(inbox_rate) as best_rate FROM admin.brain_configs")->fetch(PDO::FETCH_ASSOC);
$seedStats = $pdo->query("SELECT COUNT(*) as total, COUNT(CASE WHEN is_active THEN 1 END) as active FROM admin.brain_seeds")->fetch(PDO::FETCH_ASSOC);
$ispStats = $pdo->query("SELECT isp_target, COUNT(*) as configs, AVG(inbox_rate) as avg_rate, MAX(inbox_rate) as best_rate, SUM(total_sent) as tests, COUNT(CASE WHEN is_winner THEN 1 END) as winners FROM admin.brain_configs GROUP BY isp_target ORDER BY avg_rate DESC")->fetchAll(PDO::FETCH_ASSOC);
$methodStats = $pdo->query("SELECT send_method, COUNT(*) as configs, AVG(inbox_rate) as avg_rate, COUNT(CASE WHEN is_winner THEN 1 END) as winners FROM admin.brain_configs GROUP BY send_method ORDER BY avg_rate DESC")->fetchAll(PDO::FETCH_ASSOC);
$isps = ['T-ONLINE', 'GMX', 'ZIGGO', 'GMAIL', 'OUTLOOK', 'HOTMAIL', 'ALICE', 'YAHOO', 'AOL', 'WEB.DE', 'ORANGE', 'FREE'];
$methods = ['OFFICE_365', 'GSUITE_RELAY', 'DOMAIN_IP', 'PMTA_DIRECT', 'SES', 'SENDGRID'];
$configsJson = json_encode($configs);
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🧠 Brain Engine Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body { background: linear-gradient(135deg, #0a0f1a 0%, #1a1f3a 50%, #0f1629 100%); min-height: 100vh; }
.glass { background: rgba(255,255,255,0.05); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.1); }
.winner-glow { box-shadow: 0 0 20px rgba(34, 197, 94, 0.3); }
.stat-card { cursor: pointer; transition: all 0.3s; }
.stat-card:hover { transform: translateY(-4px); border-color: rgba(139, 92, 246, 0.5); }
.config-card { cursor: pointer; transition: all 0.3s; }
.config-card:hover { transform: scale(1.01); }
.modal { display: none; }
.modal.open { display: flex; }
.param-badge { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 6px; font-size: 11px; }
.tab-btn { padding: 8px 16px; border-radius: 8px 8px 0 0; cursor: pointer; }
.tab-btn.active { background: rgba(139, 92, 246, 0.3); border-bottom: 2px solid #a855f7; }
.tab-content { display: none; }
.tab-content.active { display: block; }
.detail-section { background: rgba(0,0,0,0.3); border-radius: 12px; padding: 16px; margin-bottom: 16px; }
.detail-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.05); }
.detail-row:last-child { border-bottom: none; }
.copy-btn { cursor: pointer; padding: 2px 8px; background: rgba(255,255,255,0.1); border-radius: 4px; font-size: 10px; }
.copy-btn:hover { background: rgba(255,255,255,0.2); }
</style>
</head>
<body class="text-white p-6">
<div class="max-w-7xl mx-auto">
<div class="flex justify-between items-center mb-8">
<div class="flex items-center gap-4">
<div class="text-5xl">🧠</div>
<div><h1 class="text-3xl font-bold bg-gradient-to-r from-purple-400 via-pink-400 to-yellow-400 bg-clip-text text-transparent">BRAIN ENGINE</h1>
<p class="text-gray-400">Winning Configurations & Performance Analysis</p></div>
</div>
<div class="flex gap-3">
<button onclick="document.getElementById('addModal').classList.remove('hidden')" class="px-4 py-2 bg-purple-600 rounded-lg hover:bg-purple-500"> Add Config</button>
<a href="index.php" class="px-4 py-2 bg-gray-700 rounded-lg hover:bg-gray-600">🏠 Home</a>
</div>
</div>
<?php if (!empty($success)): ?><div class="bg-green-500/20 border border-green-500 text-green-300 p-4 rounded-lg mb-6">✅ <?= $success ?></div><?php endif; ?>
<div class="grid grid-cols-6 gap-4 mb-8">
<div class="glass rounded-xl p-4 text-center stat-card" onclick="showModal('configsModal')"><div class="text-3xl font-bold text-blue-400"><?= $stats['total_configs'] ?></div><div class="text-sm text-gray-400">Configs</div><div class="text-xs text-blue-300 mt-1">Cliquer pour détails →</div></div>
<div class="glass rounded-xl p-4 text-center stat-card winner-glow" onclick="showModal('winnersModal')"><div class="text-3xl font-bold text-green-400"><?= $stats['total_winners'] ?></div><div class="text-sm text-gray-400">Winners 🏆</div><div class="text-xs text-green-300 mt-1">Voir paramètres →</div></div>
<div class="glass rounded-xl p-4 text-center stat-card" onclick="showModal('testsModal')"><div class="text-3xl font-bold text-yellow-400"><?= $stats['total_tests'] ?? 0 ?></div><div class="text-sm text-gray-400">Tests</div><div class="text-xs text-yellow-300 mt-1">Historique →</div></div>
<div class="glass rounded-xl p-4 text-center stat-card" onclick="showModal('ispModal')"><div class="text-3xl font-bold text-purple-400"><?= number_format($stats['avg_rate'] ?? 0, 1) ?>%</div><div class="text-sm text-gray-400">Avg Rate</div><div class="text-xs text-purple-300 mt-1">Par ISP →</div></div>
<div class="glass rounded-xl p-4 text-center stat-card" onclick="showModal('methodsModal')"><div class="text-3xl font-bold text-pink-400"><?= number_format($stats['best_rate'] ?? 0, 1) ?>%</div><div class="text-sm text-gray-400">Best</div><div class="text-xs text-pink-300 mt-1">Par méthode →</div></div>
<div class="glass rounded-xl p-4 text-center stat-card" onclick="showModal('seedsModal')"><div class="text-3xl font-bold <?= ($seedStats['active'] ?? 0) > 0 ? 'text-green-400' : 'text-red-400' ?>"><?= $seedStats['active'] ?? 0 ?>/<?= $seedStats['total'] ?? 0 ?></div><div class="text-sm text-gray-400">Seeds</div><div class="text-xs text-cyan-300 mt-1">Gérer seeds →</div></div>
</div>
<div class="glass rounded-xl p-6 mb-8">
<h2 class="text-2xl font-bold text-green-400 mb-6">🏆 Winning Configurations <span class="text-sm font-normal text-gray-400">(>=80% inbox & >=10 tests)</span></h2>
<?php if (empty($winners)): ?><div class="text-center py-8 text-gray-400">Aucun winner. Continuez les tests!</div>
<?php else: foreach ($winners as $i => $w): $medal = $i === 0 ? '🥇' : ($i === 1 ? '🥈' : ($i === 2 ? '🥉' : '🏆')); ?>
<div class="config-card bg-gradient-to-r from-green-900/40 to-emerald-900/20 p-6 rounded-xl border border-green-500/30 mb-4" onclick="showDeepDrill(<?= $w['id'] ?>)">
<div class="flex justify-between items-start">
<div class="flex items-start gap-4">
<span class="text-4xl"><?= $medal ?></span>
<div>
<div class="text-xl font-bold text-white mb-2"><?= $w['isp_target'] ?> <span class="text-sm text-gray-400">#<?= $w['id'] ?></span></div>
<div class="flex flex-wrap gap-2 mb-3">
<span class="param-badge bg-blue-500/30 text-blue-300">📧 <?= $w['send_method'] ?></span>
<span class="param-badge bg-purple-500/30 text-purple-300">🌐 <?= $w['domain_used'] ?: 'N/A' ?></span>
<?php if ($w['from_email']): ?><span class="param-badge bg-cyan-500/30 text-cyan-300">✉️ <?= $w['from_email'] ?></span><?php endif; ?>
<?php if ($w['subject_template']): ?><span class="param-badge bg-pink-500/30 text-pink-300">📝 Subject: <?= substr($w['subject_template'], 0, 30) ?>...</span><?php endif; ?>
</div>
<div class="grid grid-cols-4 gap-4 text-sm">
<div><span class="text-gray-400">Inbox:</span> <span class="text-green-400 font-bold"><?= $w['inbox_count'] ?></span></div>
<div><span class="text-gray-400">Spam:</span> <span class="text-red-400"><?= $w['spam_count'] ?></span></div>
<div><span class="text-gray-400">Consec:</span> <span class="text-green-300"><?= $w['consecutive_inbox'] ?>🔥</span></div>
<div><span class="text-gray-400">Conf:</span> <span class="text-yellow-400"><?= $w['confidence_score'] ?>%</span></div>
</div>
</div>
</div>
<div class="text-right">
<div class="text-4xl font-black text-green-400"><?= number_format($w['inbox_rate'], 1) ?>%</div>
<div class="text-sm text-gray-400"><?= $w['total_sent'] ?> tests</div>
<div class="text-xs text-purple-400 mt-2">🔍 Cliquer pour tous les détails →</div>
</div>
</div>
</div>
<?php endforeach; endif; ?>
</div>
<div class="glass rounded-xl p-6 mb-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-blue-400">📊 Toutes les Configurations</h2>
<input type="text" id="searchConfigs" placeholder="🔍 Rechercher..." class="bg-gray-800 border border-gray-600 rounded-lg px-4 py-2 text-sm" onkeyup="filterTable()">
</div>
<div class="overflow-x-auto">
<table class="w-full">
<thead><tr class="border-b border-gray-700 text-left text-sm text-gray-400">
<th class="p-3">ISP</th><th class="p-3">Méthode</th><th class="p-3">Domaine</th><th class="p-3 text-center">Tests</th><th class="p-3 text-center">Inbox</th><th class="p-3 text-center">Spam</th><th class="p-3 text-center">Rate</th><th class="p-3 text-center">Status</th><th class="p-3">Actions</th>
</tr></thead>
<tbody>
<?php foreach ($configs as $c): $rate = $c['inbox_rate'] ?? 0; $color = $rate >= 80 ? 'text-green-400' : ($rate >= 50 ? 'text-yellow-400' : 'text-red-400'); ?>
<tr class="border-b border-gray-800 hover:bg-white/5 config-row cursor-pointer" onclick="showDeepDrill(<?= $c['id'] ?>)">
<td class="p-3 font-bold"><?= $c['isp_target'] ?></td>
<td class="p-3"><span class="px-2 py-1 rounded text-xs bg-blue-500/20 text-blue-300"><?= $c['send_method'] ?></span></td>
<td class="p-3 text-gray-400 text-xs font-mono"><?= $c['domain_used'] ?: '-' ?></td>
<td class="p-3 text-center"><?= $c['total_sent'] ?></td>
<td class="p-3 text-center text-green-400 font-bold"><?= $c['inbox_count'] ?></td>
<td class="p-3 text-center text-red-400"><?= $c['spam_count'] ?></td>
<td class="p-3 text-center font-bold <?= $color ?>"><?= number_format($rate, 1) ?>%</td>
<td class="p-3 text-center text-xl"><?= $c['is_winner'] ? '🏆' : ($c['total_sent'] < 10 ? '🔄' : '📊') ?></td>
<td class="p-3" onclick="event.stopPropagation();">
<form method="POST" class="inline-flex gap-1"><input type="hidden" name="config_id" value="<?= $c['id'] ?>">
<button name="action" value="mark_inbox" class="px-2 py-1 bg-green-600 hover:bg-green-500 rounded text-xs">📥</button>
<button name="action" value="mark_spam" class="px-2 py-1 bg-red-600 hover:bg-red-500 rounded text-xs">📛</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- DEEP DRILL MODAL -->
<div id="deepDrillModal" class="modal fixed inset-0 bg-black/90 items-center justify-center z-50 p-4 overflow-y-auto">
<div class="glass rounded-2xl w-full max-w-6xl my-8">
<div class="p-6 border-b border-gray-700 flex justify-between items-center sticky top-0 bg-gray-900/98 z-10">
<div><h3 class="text-2xl font-bold" id="drillTitle">Config Details</h3><div class="text-sm text-gray-400" id="drillSubtitle"></div></div>
<div class="flex gap-2">
<button onclick="copyConfig()" class="px-3 py-1 bg-gray-700 rounded text-sm">📋 Copy JSON</button>
<button onclick="exportPMTA()" class="px-3 py-1 bg-purple-600 rounded text-sm">📤 Export PMTA</button>
<button onclick="closeModal('deepDrillModal')" class="text-3xl text-gray-400 hover:text-white ml-4">&times;</button>
</div>
</div>
<div class="p-6" id="drillContent"></div>
</div>
</div>
<!-- ISP Modal -->
<div id="ispModal" class="modal fixed inset-0 bg-black/80 items-center justify-center z-50 p-4">
<div class="glass rounded-2xl w-full max-w-3xl max-h-[90vh] overflow-y-auto">
<div class="p-6 border-b border-gray-700 flex justify-between items-center"><h3 class="text-2xl font-bold text-purple-400">📊 Performance par ISP</h3><button onclick="closeModal('ispModal')" class="text-3xl">&times;</button></div>
<div class="p-6"><?php foreach ($ispStats as $isp): $color = ($isp['avg_rate'] ?? 0) >= 70 ? 'bg-green-500' : 'bg-yellow-500'; ?>
<div class="mb-4"><div class="flex justify-between mb-1"><span class="font-bold"><?= $isp['isp_target'] ?></span><span class="text-sm text-gray-400"><?= $isp['configs'] ?> configs | <?= $isp['winners'] ?> winners</span></div>
<div class="w-full bg-gray-700 rounded-full h-4"><div class="<?= $color ?> h-4 rounded-full" style="width:<?= min(100, $isp['avg_rate'] ?? 0) ?>%"></div></div>
<div class="text-xs text-gray-500"><?= number_format($isp['avg_rate'] ?? 0, 1) ?>% avg | Best: <?= number_format($isp['best_rate'] ?? 0, 1) ?>%</div></div>
<?php endforeach; ?></div>
</div>
</div>
<!-- Methods Modal -->
<div id="methodsModal" class="modal fixed inset-0 bg-black/80 items-center justify-center z-50 p-4">
<div class="glass rounded-2xl w-full max-w-3xl max-h-[90vh] overflow-y-auto">
<div class="p-6 border-b border-gray-700 flex justify-between items-center"><h3 class="text-2xl font-bold text-pink-400">📧 Performance par Méthode</h3><button onclick="closeModal('methodsModal')" class="text-3xl">&times;</button></div>
<div class="p-6"><?php foreach ($methodStats as $m): ?>
<div class="bg-gray-800 p-4 rounded-lg mb-3 flex justify-between items-center"><div><div class="font-bold"><?= $m['send_method'] ?></div><div class="text-sm text-gray-400"><?= $m['configs'] ?> configs | <?= $m['winners'] ?> winners</div></div>
<div class="text-3xl font-bold <?= ($m['avg_rate'] ?? 0) >= 70 ? 'text-green-400' : 'text-yellow-400' ?>"><?= number_format($m['avg_rate'] ?? 0, 1) ?>%</div></div>
<?php endforeach; ?></div>
</div>
</div>
<!-- Other Modals -->
<div id="winnersModal" class="modal fixed inset-0 bg-black/80 items-center justify-center z-50 p-4"><div class="glass rounded-2xl w-full max-w-3xl max-h-[90vh] overflow-y-auto"><div class="p-6 border-b border-gray-700 flex justify-between items-center"><h3 class="text-2xl font-bold text-green-400">🏆 Winners Analysis</h3><button onclick="closeModal('winnersModal')" class="text-3xl">&times;</button></div><div class="p-6"><p class="text-gray-400">Cliquez sur un winner dans la liste principale pour voir tous ses détails.</p></div></div></div>
<div id="seedsModal" class="modal fixed inset-0 bg-black/80 items-center justify-center z-50 p-4"><div class="glass rounded-2xl w-full max-w-3xl max-h-[90vh] overflow-y-auto"><div class="p-6 border-b border-gray-700 flex justify-between items-center"><h3 class="text-2xl font-bold text-cyan-400">🌱 Seeds</h3><button onclick="closeModal('seedsModal')" class="text-3xl">&times;</button></div><div class="p-6 grid grid-cols-2 gap-3"><?php foreach ($seeds as $seed): ?><div class="p-3 rounded-lg <?= $seed['is_active'] ? 'bg-green-900/20' : 'bg-red-900/20' ?>"><div class="font-bold truncate"><?= $seed['email'] ?></div><div class="text-sm text-gray-400"><?= $seed['isp'] ?> <?= $seed['is_active'] ? '✅' : '❌' ?></div></div><?php endforeach; ?></div></div></div>
<div id="configsModal" class="modal fixed inset-0 bg-black/80 items-center justify-center z-50 p-4"><div class="glass rounded-2xl w-full max-w-4xl max-h-[90vh] overflow-y-auto"><div class="p-6 border-b border-gray-700 flex justify-between items-center sticky top-0 bg-gray-900/98"><h3 class="text-2xl font-bold text-blue-400">📋 Configs - Level 2 Drill</h3><button onclick="closeModal('configsModal')" class="text-3xl">&times;</button></div><div class="p-6"><div class="grid grid-cols-3 gap-4 mb-6"><div class="bg-green-500/10 p-4 rounded-lg text-center cursor-pointer hover:bg-green-500/20" onclick="showConfigCategory('winners')"><div class="text-3xl font-bold text-green-400"><?= $stats['total_winners'] ?></div><div class="text-sm">Winners 🏆</div><div class="text-xs text-green-300 mt-1">Click pour liste →</div></div><div class="bg-yellow-500/10 p-4 rounded-lg text-center cursor-pointer hover:bg-yellow-500/20" onclick="showConfigCategory('testing')"><div class="text-3xl font-bold text-yellow-400"><?= count(array_filter($configs, fn($c) => !$c['is_winner'] && $c['total_sent'] >= 5)) ?></div><div class="text-sm">Testing 🔄</div><div class="text-xs text-yellow-300 mt-1">Click pour liste →</div></div><div class="bg-gray-500/10 p-4 rounded-lg text-center cursor-pointer hover:bg-gray-500/20" onclick="showConfigCategory('new')"><div class="text-3xl font-bold text-gray-400"><?= count(array_filter($configs, fn($c) => $c['total_sent'] < 5)) ?></div><div class="text-sm">New 🆕</div><div class="text-xs text-gray-300 mt-1">Click pour liste →</div></div></div><div id="configCategoryDetail" class="hidden"><h4 id="categoryTitle" class="font-bold text-lg mb-4"></h4><div id="categoryList" class="space-y-2 max-h-80 overflow-y-auto"></div></div></div></div></div>
<div id="testsModal" class="modal fixed inset-0 bg-black/80 items-center justify-center z-50 p-4"><div class="glass rounded-2xl w-full max-w-3xl"><div class="p-6 border-b border-gray-700 flex justify-between items-center"><h3 class="text-2xl font-bold text-yellow-400">🧪 Tests</h3><button onclick="closeModal('testsModal')" class="text-3xl">&times;</button></div><div class="p-6"><div class="grid grid-cols-2 gap-4"><div class="bg-green-500/10 p-4 rounded-lg text-center"><div class="text-3xl font-bold text-green-400"><?= array_sum(array_column($configs, 'inbox_count')) ?></div><div class="text-sm">Inbox</div></div><div class="bg-red-500/10 p-4 rounded-lg text-center"><div class="text-3xl font-bold text-red-400"><?= array_sum(array_column($configs, 'spam_count')) ?></div><div class="text-sm">Spam</div></div></div></div></div></div>
<!-- Add Modal -->
<div id="addModal" class="hidden fixed inset-0 bg-black/70 flex items-center justify-center z-50">
<div class="glass rounded-xl p-6 w-full max-w-lg">
<h3 class="text-xl font-bold mb-4"> Nouvelle Config</h3>
<form method="POST"><input type="hidden" name="action" value="add_config">
<div class="grid grid-cols-2 gap-4">
<div><label class="text-sm text-gray-400">ISP *</label><select name="isp_target" required class="w-full bg-gray-800 border border-gray-600 rounded p-2"><?php foreach ($isps as $isp): ?><option><?= $isp ?></option><?php endforeach; ?></select></div>
<div><label class="text-sm text-gray-400">Méthode *</label><select name="send_method" required class="w-full bg-gray-800 border border-gray-600 rounded p-2"><?php foreach ($methods as $m): ?><option><?= $m ?></option><?php endforeach; ?></select></div>
<div class="col-span-2"><label class="text-sm text-gray-400">Domaine</label><input name="domain_used" class="w-full bg-gray-800 border border-gray-600 rounded p-2"></div>
<div><label class="text-sm text-gray-400">From Email</label><input name="from_email" class="w-full bg-gray-800 border border-gray-600 rounded p-2"></div>
<div><label class="text-sm text-gray-400">Subject</label><input name="subject_template" class="w-full bg-gray-800 border border-gray-600 rounded p-2"></div>
</div>
<div class="flex justify-end gap-3 mt-4">
<button type="button" onclick="document.getElementById('addModal').classList.add('hidden')" class="px-4 py-2 bg-gray-600 rounded">Annuler</button>
<button type="submit" class="px-4 py-2 bg-purple-600 rounded">💾 Save</button>
</div>
</form>
</div>
</div>
</div>
<script>
const allConfigs = <?= $configsJson ?>;
let currentConfig = null;
function showModal(id) { document.getElementById(id).classList.add('open'); }
function closeModal(id) { document.getElementById(id).classList.remove('open'); }
function showDeepDrill(configId) {
currentConfig = allConfigs.find(c => c.id == configId);
if (!currentConfig) return;
const c = currentConfig;
document.getElementById('drillTitle').innerHTML = `${c.is_winner ? '🏆' : '📊'} ${c.isp_target} - ${c.send_method}`;
document.getElementById('drillSubtitle').innerHTML = `Config #${c.id} | ${c.total_sent} tests | ${Number(c.inbox_rate).toFixed(1)}% inbox`;
document.getElementById('drillContent').innerHTML = `
<div class="flex gap-2 mb-6 border-b border-gray-700 pb-2 overflow-x-auto">
<button class="tab-btn active" onclick="showTab('overview')">📋 Overview</button>
<button class="tab-btn" onclick="showTab('email')">✉️ Email</button>
<button class="tab-btn" onclick="showTab('headers')">📝 Headers</button>
<button class="tab-btn" onclick="showTab('dns')">🔐 DNS/Auth</button>
<button class="tab-btn" onclick="showTab('body')">📄 Body</button>
<button class="tab-btn" onclick="showTab('tracking')">📊 Tracking</button>
<button class="tab-btn" onclick="showTab('pmta')">⚙️ PMTA</button>
<button class="tab-btn" onclick="showTab('raw')">🔧 Raw</button>
</div>
<div id="tab-overview" class="tab-content active">
<div class="grid grid-cols-2 gap-6">
<div class="detail-section">
<h5 class="text-green-400 font-bold mb-4">📈 Performance Metrics</h5>
<div class="text-center mb-4">
<div class="text-6xl font-black ${c.inbox_rate >= 80 ? 'text-green-400' : c.inbox_rate >= 50 ? 'text-yellow-400' : 'text-red-400'}">${Number(c.inbox_rate).toFixed(1)}%</div>
<div class="text-gray-400">Inbox Rate</div>
</div>
<div class="grid grid-cols-2 gap-3">
<div class="bg-green-900/30 p-3 rounded text-center"><div class="text-2xl font-bold text-green-400">${c.inbox_count}</div><div class="text-xs text-gray-400">Inbox</div></div>
<div class="bg-red-900/30 p-3 rounded text-center"><div class="text-2xl font-bold text-red-400">${c.spam_count}</div><div class="text-xs text-gray-400">Spam</div></div>
<div class="bg-yellow-900/30 p-3 rounded text-center"><div class="text-2xl font-bold text-yellow-400">${c.confidence_score}%</div><div class="text-xs text-gray-400">Confidence</div></div>
<div class="bg-purple-900/30 p-3 rounded text-center"><div class="text-2xl font-bold text-purple-400">${c.stability_score || 0}%</div><div class="text-xs text-gray-400">Stability</div></div>
</div>
<div class="mt-4 text-sm space-y-2">
<div class="detail-row"><span class="text-gray-400">Consecutive Inbox</span><span class="text-green-400 font-bold">${c.consecutive_inbox} 🔥</span></div>
<div class="detail-row"><span class="text-gray-400">Consecutive Spam</span><span class="text-red-400">${c.consecutive_spam}</span></div>
<div class="detail-row"><span class="text-gray-400">Bounce Count</span><span>${c.bounce_count || 0}</span></div>
<div class="detail-row"><span class="text-gray-400">Last Success</span><span>${c.last_success_at || 'Never'}</span></div>
</div>
</div>
<div class="detail-section">
<h5 class="${c.is_winner ? 'text-green-400' : 'text-yellow-400'} font-bold mb-4">${c.is_winner ? '🏆 Winning Factors' : '📈 Path to Winner'}</h5>
${c.is_winner ? `
<div class="bg-green-900/30 p-4 rounded-lg border border-green-500/50 mb-4">
<ul class="text-sm space-y-2">
<li>✅ High inbox rate: ${Number(c.inbox_rate).toFixed(1)}%</li>
<li>✅ Sufficient tests: ${c.total_sent}</li>
<li>✅ Confidence: ${c.confidence_score}%</li>
<li>✅ Method: ${c.send_method}</li>
${c.domain_used ? `<li>✅ Domain: ${c.domain_used}</li>` : ''}
</ul>
</div>` : `
<div class="bg-yellow-900/30 p-4 rounded-lg border border-yellow-500/50 mb-4">
<ul class="text-sm space-y-2">
<li>${c.inbox_rate >= 80 ? '✅' : '❌'} Rate >= 80% (${Number(c.inbox_rate).toFixed(1)}%)</li>
<li>${c.total_sent >= 10 ? '✅' : '❌'} Tests >= 10 (${c.total_sent})</li>
<li>Need ${Math.max(0, 10 - c.total_sent)} more tests</li>
</ul>
</div>`}
<div class="text-sm space-y-2">
<div class="detail-row"><span class="text-gray-400">Status</span><span>${c.status || 'learning'}</span></div>
<div class="detail-row"><span class="text-gray-400">Source</span><span>${c.source || 'manual'}</span></div>
<div class="detail-row"><span class="text-gray-400">Created</span><span>${c.created_at}</span></div>
</div>
</div>
</div>
</div>
<div id="tab-email" class="tab-content">
<div class="grid grid-cols-2 gap-6">
<div class="detail-section">
<h5 class="text-blue-400 font-bold mb-4">📧 Sender Configuration</h5>
<div class="space-y-2 text-sm">
<div class="detail-row"><span class="text-gray-400">ISP Target</span><span class="font-bold">${c.isp_target}</span></div>
<div class="detail-row"><span class="text-gray-400">Send Method</span><span class="text-blue-400">${c.send_method}</span></div>
<div class="detail-row"><span class="text-gray-400">SMTP Type</span><span>${c.smtp_type || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">SMTP Account ID</span><span>${c.smtp_account_id || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">Domain</span><span class="font-mono text-purple-400">${c.domain_used || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">IP Used</span><span class="font-mono text-orange-400">${c.ip_used || 'N/A'}</span></div>
</div>
</div>
<div class="detail-section">
<h5 class="text-cyan-400 font-bold mb-4">✉️ Email Identity</h5>
<div class="space-y-2 text-sm">
<div class="detail-row"><span class="text-gray-400">From Name</span><span>${c.from_name || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">From Email</span><span class="text-cyan-400">${c.from_email || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">Reply-To</span><span>${c.reply_to || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">Return-Path</span><span class="font-mono text-xs">${c.return_path || 'N/A'}</span></div>
</div>
</div>
</div>
<div class="detail-section">
<h5 class="text-pink-400 font-bold mb-4">📝 Content Config</h5>
<div class="grid grid-cols-3 gap-4 text-sm">
<div class="detail-row"><span class="text-gray-400">Content-Type</span><span>${c.content_type || 'text/html'}</span></div>
<div class="detail-row"><span class="text-gray-400">Encoding</span><span>${c.encoding || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">Charset</span><span>${c.charset || 'utf-8'}</span></div>
</div>
<div class="mt-4"><div class="text-gray-400 text-sm mb-2">Subject Template</div><div class="bg-gray-800 p-3 rounded font-mono text-sm">${c.subject_template || 'N/A'}</div></div>
</div>
</div>
<div id="tab-headers" class="tab-content">
<div class="detail-section">
<h5 class="text-yellow-400 font-bold mb-4">📝 Custom Headers (Critical for Deliverability)</h5>
<table class="w-full text-sm">
<thead><tr class="border-b border-gray-700"><th class="p-2 text-left text-gray-400">#</th><th class="p-2 text-left text-gray-400">Header Name</th><th class="p-2 text-left text-gray-400">Value</th><th class="p-2 text-gray-400">Status</th></tr></thead>
<tbody>
${[1,2,3,4,5].map(i => `<tr class="border-b border-gray-800">
<td class="p-2 text-gray-500">${i}</td>
<td class="p-2 font-mono text-blue-400">${c['header_'+i+'_name'] || '-'}</td>
<td class="p-2 font-mono text-xs max-w-xs truncate">${c['header_'+i+'_value'] || '-'}</td>
<td class="p-2"><span class="text-xs px-2 py-1 rounded ${c['header_'+i+'_name'] ? 'bg-green-500/20 text-green-300' : 'bg-gray-500/20 text-gray-400'}">${c['header_'+i+'_name'] ? 'Active' : 'Empty'}</span></td>
</tr>`).join('')}
</tbody>
</table>
</div>
<div class="detail-section">
<h5 class="text-purple-400 font-bold mb-4">🔍 Header Analysis</h5>
<div class="grid grid-cols-2 gap-4">
<div class="bg-gray-800 p-4 rounded"><div class="text-gray-400 text-sm mb-1">X-Mailer</div><div class="font-mono">${c.header_1_name === 'X-Mailer' ? c.header_1_value : 'Not set'}</div><div class="text-xs text-gray-500 mt-1">Tip: Exchange sans X-Mailer = 97% inbox</div></div>
<div class="bg-gray-800 p-4 rounded"><div class="text-gray-400 text-sm mb-1">List-Unsubscribe</div><div class="font-mono text-xs truncate">${c.list_unsubscribe || 'Not set'}</div><div class="text-xs text-gray-500 mt-1">Required for Gmail/Outlook bulk</div></div>
</div>
</div>
</div>
<div id="tab-dns" class="tab-content">
<div class="detail-section">
<h5 class="text-green-400 font-bold mb-4">🔐 Authentication Records</h5>
<div class="space-y-4">
<div class="bg-gray-800 p-4 rounded-lg">
<div class="flex justify-between items-center mb-2"><span class="font-bold text-blue-400">SPF Record</span><span class="text-xs px-2 py-1 rounded ${c.spf_record ? 'bg-green-500/20 text-green-300' : 'bg-red-500/20 text-red-300'}">${c.spf_record ? '✅ Set' : '❌ Missing'}</span></div>
<div class="font-mono text-xs bg-gray-900 p-2 rounded overflow-x-auto">${c.spf_record || 'v=spf1 include:spf.protection.outlook.com -all'}</div>
</div>
<div class="bg-gray-800 p-4 rounded-lg">
<div class="flex justify-between items-center mb-2"><span class="font-bold text-purple-400">DKIM Selector</span><span class="text-xs px-2 py-1 rounded ${c.dkim_selector ? 'bg-green-500/20 text-green-300' : 'bg-yellow-500/20 text-yellow-300'}">${c.dkim_selector ? '✅ Set' : '⚠️ Default'}</span></div>
<div class="font-mono">${c.dkim_selector || 'selector1'}</div>
</div>
<div class="bg-gray-800 p-4 rounded-lg">
<div class="flex justify-between items-center mb-2"><span class="font-bold text-orange-400">DMARC Policy</span><span class="text-xs px-2 py-1 rounded ${c.dmarc_policy ? 'bg-green-500/20 text-green-300' : 'bg-yellow-500/20 text-yellow-300'}">${c.dmarc_policy ? '✅ Set' : '⚠️ None'}</span></div>
<div class="font-mono">${c.dmarc_policy || 'none'}</div>
</div>
</div>
</div>
</div>
<div id="tab-body" class="tab-content">
<div class="detail-section">
<h5 class="text-pink-400 font-bold mb-4">📄 Email Body Template</h5>
${c.body_template ? `
<div class="bg-gray-900 p-4 rounded-lg font-mono text-xs max-h-96 overflow-auto whitespace-pre-wrap">${c.body_template.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</div>
<div class="mt-4 flex gap-2">
<button onclick="copyBody()" class="px-3 py-1 bg-gray-700 rounded text-sm">📋 Copy Body</button>
<button onclick="previewBody()" class="px-3 py-1 bg-blue-600 rounded text-sm">👁️ Preview HTML</button>
</div>
` : '<p class="text-gray-400">No body template configured</p>'}
</div>
<div class="detail-section">
<h5 class="text-cyan-400 font-bold mb-4">🔗 Links & Assets</h5>
<div class="space-y-2 text-sm">
<div class="detail-row"><span class="text-gray-400">Link URL</span><span class="font-mono text-xs truncate max-w-md">${c.link_url || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">Image URL</span><span class="font-mono text-xs truncate max-w-md">${c.image_url || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">Unsubscribe URL</span><span class="font-mono text-xs truncate max-w-md">${c.unsubscribe_url || 'N/A'}</span></div>
</div>
</div>
</div>
<div id="tab-tracking" class="tab-content">
<div class="detail-section">
<h5 class="text-orange-400 font-bold mb-4">📊 Tracking Configuration</h5>
<div class="space-y-2 text-sm">
<div class="detail-row"><span class="text-gray-400">Tracking Domain</span><span class="font-mono">${c.tracking_domain || 'N/A'}</span></div>
<div class="detail-row"><span class="text-gray-400">Redirect Domain</span><span class="font-mono">${c.redirect_domain || 'N/A'}</span></div>
</div>
</div>
</div>
<div id="tab-pmta" class="tab-content">
<div class="detail-section">
<h5 class="text-red-400 font-bold mb-4">⚙️ PMTA Configuration</h5>
<div class="space-y-2 text-sm mb-4">
<div class="detail-row"><span class="text-gray-400">PMTA Version</span><span>${c.pmta_version || '5.0r3'}</span></div>
<div class="detail-row"><span class="text-gray-400">Config Hash</span><span class="font-mono text-xs">${c.config_hash || 'N/A'}</span></div>
</div>
<div class="bg-gray-900 p-4 rounded-lg font-mono text-xs">
<pre># PMTA Config for ${c.isp_target} - ${c.send_method}
# Generated from Brain Engine Config #${c.id}
<domain ${c.isp_target.toLowerCase()}.com>
max-smtp-out 10
smtp-pattern-lifetime 1h
</domain>
<source ${c.ip_used || '0.0.0.0'}>
smtp-source-host ${c.ip_used || '0.0.0.0'} ${c.domain_used || 'example.com'}
max-msg-rate 100/h
</source>
# Headers
${c.header_1_name ? `header-${c.header_1_name}: ${c.header_1_value}` : '# No custom headers'}
${c.header_2_name ? `header-${c.header_2_name}: ${c.header_2_value}` : ''}
# Authentication
dkim-sign yes
dkim-selector ${c.dkim_selector || 'selector1'}
</pre>
</div>
<button onclick="copyPMTA()" class="mt-4 px-4 py-2 bg-red-600 rounded text-sm">📋 Copy PMTA Config</button>
</div>
</div>
<div id="tab-raw" class="tab-content">
<div class="detail-section">
<h5 class="text-gray-400 font-bold mb-4">🔧 Raw JSON Data</h5>
<pre class="bg-gray-900 p-4 rounded text-xs overflow-auto max-h-96">${JSON.stringify(c, null, 2)}</pre>
<button onclick="copyConfig()" class="mt-4 px-4 py-2 bg-gray-700 rounded text-sm">📋 Copy JSON</button>
</div>
</div>
`;
showModal('deepDrillModal');
}
function showTab(name) {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
document.querySelector(`[onclick="showTab('${name}')"]`).classList.add('active');
document.getElementById('tab-' + name).classList.add('active');
}
function copyConfig() { navigator.clipboard.writeText(JSON.stringify(currentConfig, null, 2)); alert('Copied!'); }
function copyBody() { navigator.clipboard.writeText(currentConfig.body_template || ''); alert('Body copied!'); }
function copyPMTA() {
const pmta = document.querySelector('#tab-pmta pre').textContent;
navigator.clipboard.writeText(pmta);
alert('PMTA config copied!');
}
function exportPMTA() { copyPMTA(); }
function previewBody() {
const w = window.open('', '_blank');
w.document.write(currentConfig.body_template || '<p>No body</p>');
}
function filterTable() {
function showConfigCategory(cat) {
const configs = allConfigs;
let filtered = [];
let title = "";
let color = "";
if (cat === "winners") {
filtered = configs.filter(c => c.is_winner);
title = "🏆 Winners - Configs Gagnantes";
color = "green";
} else if (cat === "testing") {
filtered = configs.filter(c => !c.is_winner && c.total_sent >= 5);
title = "🔄 Testing - En cours de test";
color = "yellow";
} else {
filtered = configs.filter(c => c.total_sent < 5);
title = "🆕 New - Nouvelles configs";
color = "gray";
}
let html = `<div class="mt-4 p-4 bg-gray-800 rounded-lg border border-${color}-500/30">
<h4 class="font-bold mb-3 text-${color}-400">${title} (${filtered.length})</h4>
<div class="space-y-2 max-h-60 overflow-y-auto">`;
if (filtered.length === 0) {
html += '<p class="text-gray-500">Aucune config dans cette catégorie</p>';
} else {
filtered.forEach(c => {
html += `<div class="flex justify-between items-center p-3 bg-gray-700/50 rounded cursor-pointer hover:bg-gray-600" onclick="closeModal('configsModal');showDeepDrill(${c.id})">
<div>
<span class="font-bold">${c.isp_target}</span>
<span class="text-gray-400 text-sm ml-2">${c.send_method}</span>
<span class="text-gray-500 text-xs ml-2">${c.domain_used || ''}</span>
</div>
<div class="text-right">
<span class="font-bold ${c.inbox_rate >= 80 ? 'text-green-400' : c.inbox_rate >= 50 ? 'text-yellow-400' : 'text-red-400'}">${Number(c.inbox_rate).toFixed(1)}%</span>
<span class="text-gray-500 text-xs ml-2">${c.total_sent} tests</span>
</div>
</div>`;
});
}
html += '</div></div>';
// Remove previous category detail if exists
const existing = document.getElementById('categoryDetail');
if (existing) existing.remove();
const container = document.createElement('div');
container.id = 'categoryDetail';
container.innerHTML = html;
document.querySelector('#configsModal .p-6').appendChild(container);
}
const q = document.getElementById('searchConfigs').value.toLowerCase();
document.querySelectorAll('.config-row').forEach(r => r.style.display = r.textContent.toLowerCase().includes(q) ? '' : 'none');
}
function showConfigCategory(cat) {
const configs = allConfigs;
let filtered = [];
let title = "";
if (cat === "winners") {
filtered = configs.filter(c => c.is_winner);
title = "🏆 Winners - Configs Gagnantes";
} else if (cat === "testing") {
filtered = configs.filter(c => !c.is_winner && c.total_sent >= 5);
title = "🔄 Testing - En cours de test";
} else {
filtered = configs.filter(c => c.total_sent < 5);
title = "🆕 New - Nouvelles configs";
}
let html = `<div class="mt-4 p-4 bg-gray-800 rounded-lg"><h4 class="font-bold mb-3">${title} (${filtered.length})</h4><div class="space-y-2 max-h-60 overflow-y-auto">`;
filtered.forEach(c => {
html += `<div class="flex justify-between items-center p-2 bg-gray-700 rounded cursor-pointer hover:bg-gray-600" onclick="closeModal('configsModal');showDeepDrill(${c.id})">`;
html += `<div><span class="font-bold">${c.isp_target}</span> <span class="text-gray-400 text-sm">${c.send_method}</span></div>`;
html += `<span class="font-bold ${c.inbox_rate >= 80 ? "text-green-400" : "text-yellow-400"}">${Number(c.inbox_rate).toFixed(1)}%</span></div>`;
});
html += "</div></div>";
document.querySelector("#configsModal .p-6:last-child").innerHTML += html;
}
document.querySelectorAll(".modal").forEach(m => m.addEventListener('click', e => { if (e.target === m) closeModal(m.id); }));
</script>
</body>
</html>