Files
html/office-365/office-workflow.php
2026-04-16 21:12:05 +02:00

356 lines
28 KiB
PHP

<?php
include_once("/opt/wevads-arsenal/public/api/wevads-metrics.php");
header("Content-Type: text/html; charset=UTF-8");
/* OPUS3-DB-HOST-FIX */ @$db=new PDO("pgsql:host=10.1.0.3;dbname=adx_system","admin","admin123",[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC]);
$db->exec("SET search_path TO admin,public");
$SN=['Register','Verify Email','DNS Setup','Domain Verify','Exchange Config','AntiSpam','Warmup','Live'];
// === ACTIONS ===
$msg='';
if($_SERVER['REQUEST_METHOD']==='POST'){
$aid=(int)($_POST['aid']??0);
$act=$_POST['act']??'';
if($act==='advance'&&$aid){
$cur=(int)$db->query("SELECT current_step FROM office_accounts WHERE id=$aid")->fetchColumn();
if($cur<7){$db->exec("UPDATE office_accounts SET current_step=".($cur+1)." WHERE id=$aid");$msg="✅ Account #$aid → Step ".($cur+1).": ".$SN[$cur+1];}
}
if($act==='retreat'&&$aid){
$cur=(int)$db->query("SELECT current_step FROM office_accounts WHERE id=$aid")->fetchColumn();
if($cur>0){$db->exec("UPDATE office_accounts SET current_step=".($cur-1)." WHERE id=$aid");$msg="⬅ Account #$aid → Step ".($cur-1).": ".$SN[$cur-1];}
}
if($act==='setstatus'&&$aid){
$ns=preg_replace('/[^a-z]/','',strtolower($_POST['ns']??''));
if(in_array($ns,['active','warming','suspended','blocked','pending'])){
$db->exec("UPDATE office_accounts SET status='$ns' WHERE id=$aid");$msg="✅ Account #$aid → Status: $ns";
}
}
if($act==='batch_advance'){
$bs=(int)($_POST['bs']??-1);
if($bs>=0&&$bs<7){
$n=$db->exec("UPDATE office_accounts SET current_step=".($bs+1)." WHERE current_step=$bs AND LOWER(status) IN ('active','warming','pending')");
$msg="✅ Batch: $n comptes Step $bs → Step ".($bs+1);
}
}
if($act==='exchange_on'&&$aid){$db->exec("UPDATE office_accounts SET exchange_configured=true WHERE id=$aid");$msg="✅ Exchange activé #$aid";}
if($act==='exchange_off'&&$aid){$db->exec("UPDATE office_accounts SET exchange_configured=false WHERE id=$aid");$msg="❌ Exchange désactivé #$aid";}
// OPUS3-OFFICE-FACTORY -- Factory Create + Recovery + Batch Recovery
if($act==='factory_create'){
$t=$_POST['tenant']??'';$c=(int)($_POST['count']??1);$p=$_POST['prefix']??'user';
if($t&&$c>0&&$c<=50){
$cr=0;
for($i=0;$i<$c;$i++){
$nm=$p.rand(100,999);
$db->exec("INSERT INTO office_accounts (name,tenant_domain,status,current_step,domains_count,has_license,exchange_configured) VALUES ('$nm','$t','pending',0,0,false,false)");
$cr++;
}
$msg="Factory: $cr comptes crees sur $t";
} else $msg="Factory: tenant requis, count 1-50";
}
if($act==='recovery'&&$aid){
$db->exec("UPDATE office_accounts SET status='active',current_step=0 WHERE id=$aid");
$msg="Recovery #$aid: reset Active Step 0";
}
if($act==='batch_recovery'){
$t=$_POST['tenant']??'';
if($t){
$n2=$db->exec("UPDATE office_accounts SET status='active',current_step=0 WHERE tenant_domain='$t' AND LOWER(status) IN ('suspended','blocked')");
$msg="Batch Recovery: $n2 comptes reactives sur $t";
}
}
if($act==='add_graph_tenant'){
$tn=$_POST['tname']??'';$td=$_POST['tid']??'';$ci=$_POST['cid']??'';$cs2=$_POST['cs']??'';
if($tn&&$td&&$ci&&$cs2){
$db->exec("INSERT INTO graph_tenants (tenant_domain,tenant_id,client_id,client_secret,status,daily_limit) VALUES ('$tn','$td','$ci','$cs2','active',10000) ON CONFLICT DO NOTHING");
$msg="Tenant $tn ajoute";
}
}
if(!isset($_GET['account_id']))header("Location:office-workflow.php".($msg?"?msg=".urlencode($msg):""));
}
if(!$msg)$msg=$_GET['msg']??'';
// === DRILL-DOWN MODE ===
$drill=(int)($_GET['account_id']??0);
if($drill){
$acc=$db->query("SELECT * FROM office_accounts WHERE id=$drill")->fetch();
if(!$acc){echo"<h1>Account #$drill not found</h1>";exit;}
$doms=$db->query("SELECT * FROM office_domains WHERE account_id=$drill ORDER BY domain_name")->fetchAll();
$tenant=$db->query("SELECT * FROM graph_tenants WHERE tenant_domain='".$acc['tenant_domain']."' LIMIT 1")->fetch();
?><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Account #<?=$drill?> — Office Workflow</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
:root{--bg:#060a14;--s:#0c1220;--s2:#111827;--b:#1e293b;--t:#e2e8f0;--d:#64748b;--cy:#22d3ee;--gn:#34d399;--am:#fbbf24;--rd:#f87171;--pu:#a78bfa;--bl:#60a5fa}
*{margin:0;padding:0;box-sizing:border-box}body{background:var(--bg);color:var(--t);font-family:'DM Sans',sans-serif;font-size:13px}
.app{max-width:1200px;margin:0 auto;padding:20px}
.card{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:20px;margin-bottom:16px}
h1{font-size:22px;margin-bottom:4px}h1 b{color:var(--bl)}h2{font-size:16px;margin-bottom:12px;color:var(--cy)}
.mono{font-family:'JetBrains Mono',monospace}
.nt{display:inline-block;padding:3px 10px;border-radius:5px;font-size:10px;font-weight:600}
.nt-g{background:rgba(52,211,153,.15);color:var(--gn)}.nt-r{background:rgba(248,113,113,.15);color:var(--rd)}.nt-a{background:rgba(251,191,36,.15);color:var(--am)}.nt-b{background:rgba(96,165,250,.15);color:var(--bl)}.nt-p{background:rgba(167,139,250,.15);color:var(--pu)}
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}
.kv{padding:12px;background:var(--s2);border-radius:6px}.kv .label{font-size:9px;color:var(--d);text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px}.kv .val{font-size:18px;font-weight:700}
.pipeline{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin:20px 0}
.step{flex:1;min-width:100px;text-align:center;padding:14px 8px;border-radius:8px;border:2px solid var(--b);position:relative;transition:.3s}
.step.done{border-color:var(--gn);background:rgba(52,211,153,.05)}.step.current{border-color:var(--cy);background:rgba(34,211,238,.1);box-shadow:0 0 20px rgba(34,211,238,.15)}.step.todo{opacity:.4}
.step .num{font-family:'JetBrains Mono',monospace;font-size:22px;font-weight:700}.step .name{font-size:9px;color:var(--d);margin-top:2px;text-transform:uppercase}
.step.done .num{color:var(--gn)}.step.current .num{color:var(--cy)}.step.todo .num{color:var(--d)}
.arrow{color:var(--d);font-size:16px}
.actions{display:flex;gap:8px;flex-wrap:wrap;margin:16px 0}
.btn{padding:8px 16px;border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;border:none;transition:.2s;text-decoration:none;display:inline-block}
.btn-cy{background:rgba(34,211,238,.15);color:var(--cy)}.btn-cy:hover{background:rgba(34,211,238,.3)}
.btn-gn{background:rgba(52,211,153,.15);color:var(--gn)}.btn-gn:hover{background:rgba(52,211,153,.3)}
.btn-am{background:rgba(251,191,36,.15);color:var(--am)}.btn-am:hover{background:rgba(251,191,36,.3)}
.btn-rd{background:rgba(248,113,113,.15);color:var(--rd)}.btn-rd:hover{background:rgba(248,113,113,.3)}
.btn-bl{background:rgba(96,165,250,.15);color:var(--bl)}.btn-bl:hover{background:rgba(96,165,250,.3)}
.btn-pu{background:rgba(167,139,250,.15);color:var(--pu)}.btn-pu:hover{background:rgba(167,139,250,.3)}
table{width:100%;border-collapse:collapse}th{text-align:left;padding:8px;color:var(--d);font-size:9px;text-transform:uppercase;border-bottom:1px solid var(--b)}td{padding:8px;border-bottom:1px solid rgba(30,41,59,.3);font-size:12px}
.back{color:var(--bl);text-decoration:none;font-size:12px;display:inline-block;margin-bottom:16px}.back:hover{text-decoration:underline}
.toast{position:fixed;top:20px;right:20px;background:var(--gn);color:#000;padding:10px 20px;border-radius:8px;font-weight:600;z-index:999;animation:fo 4s forwards}@keyframes fo{0%,70%{opacity:1}100%{opacity:0}}
</style></head><body>
<?php if($msg):?><div class="toast"><?=htmlspecialchars($msg)?></div><?php endif;?>
<div class="app">
<a href="office-workflow.php" class="back">← Back to Pipeline</a>
<div class="card">
<h1>🔍 Account <b>#<?=$drill?></b></h1>
<div style="color:var(--d);margin-top:4px"><?=htmlspecialchars($acc['name']??'')?> — <?=htmlspecialchars($acc['tenant_domain']??'')?></div>
</div>
<div class="grid">
<div class="kv"><div class="label">Status</div><div class="val"><?php $sc=strtolower($acc['status']??'');$nc=$sc==='active'?'nt-g':($sc==='warming'?'nt-a':($sc==='suspended'||$sc==='blocked'?'nt-r':'nt-b'));?><span class="nt <?=$nc?>"><?=ucfirst($sc)?></span></div></div>
<div class="kv"><div class="label">Current Step</div><div class="val mono" style="color:var(--cy)"><?=$acc['current_step']?>/7 — <?=$SN[$acc['current_step']]??'?'?></div></div>
<div class="kv"><div class="label">Exchange</div><div class="val"><?=$acc['exchange_configured']?'<span class="nt nt-g">✓ Configured</span>':'<span class="nt nt-r">✗ Not configured</span>'?></div></div>
<div class="kv"><div class="label">Domains</div><div class="val mono" style="color:var(--pu)"><?=$acc['domains_count']??0?></div></div>
</div>
<div class="card">
<h2>📊 Pipeline Progress</h2>
<div class="pipeline">
<?php for($i=0;$i<8;$i++):$cls=$i<$acc['current_step']?'done':($i==$acc['current_step']?'current':'todo');?>
<div class="step <?=$cls?>"><div class="num"><?=$i?></div><div class="name"><?=$SN[$i]?></div></div>
<?php if($i<7):?><div class="arrow"><?=$i<$acc['current_step']?'✓':'→'?></div><?php endif;endfor;?>
</div>
<h2 style="margin-top:20px">⚡ Actions</h2>
<div class="actions">
<?php if($acc['current_step']<7):?>
<form method="post" style="display:inline"><input type="hidden" name="aid" value="<?=$drill?>"><input type="hidden" name="act" value="advance">
<button class="btn btn-gn" onclick="return confirm('Avancer au Step <?=$acc['current_step']+1?>: <?=$SN[$acc['current_step']+1]?>?')">▶ Avancer → Step <?=$acc['current_step']+1?>: <?=$SN[$acc['current_step']+1]?></button></form>
<?php endif;?>
<?php if($acc['current_step']>0):?>
<form method="post" style="display:inline"><input type="hidden" name="aid" value="<?=$drill?>"><input type="hidden" name="act" value="retreat">
<button class="btn btn-am" onclick="return confirm('Reculer au Step <?=$acc['current_step']-1?>?')">◀ Reculer → Step <?=$acc['current_step']-1?></button></form>
<?php endif;?>
<form method="post" style="display:inline"><input type="hidden" name="aid" value="<?=$drill?>"><input type="hidden" name="act" value="<?=$acc['exchange_configured']?'exchange_off':'exchange_on'?>">
<button class="btn btn-pu"><?=$acc['exchange_configured']?'❌ Désactiver Exchange':'⚡ Activer Exchange'?></button></form>
</div>
<h2 style="margin-top:20px">🔄 Changer Status</h2>
<div class="actions">
<?php foreach(['active'=>'btn-gn','warming'=>'btn-am','suspended'=>'btn-rd','blocked'=>'btn-rd','pending'=>'btn-bl'] as $st=>$cls):if($st!==$sc):?>
<form method="post" style="display:inline"><input type="hidden" name="aid" value="<?=$drill?>"><input type="hidden" name="act" value="setstatus"><input type="hidden" name="ns" value="<?=$st?>">
<button class="btn <?=$cls?>"><?=ucfirst($st)?></button></form>
<?php endif;endforeach;?>
</div>
</div>
<?php if($tenant):?>
<div class="card">
<h2>🏢 Tenant: <?=htmlspecialchars($tenant['tenant_domain'])?></h2>
<div class="grid">
<div class="kv"><div class="label">Status</div><div class="val"><span class="nt <?=$tenant['status']==='active'?'nt-g':'nt-r'?>"><?=ucfirst($tenant['status'])?></span></div></div>
<div class="kv"><div class="label">Users</div><div class="val mono" style="color:var(--cy)"><?=$tenant['users_count']?></div></div>
<div class="kv"><div class="label">Sends Today</div><div class="val mono" style="color:var(--bl)"><?=$tenant['sends_today']??0?></div></div>
<div class="kv"><div class="label">Daily Limit</div><div class="val mono"><?=$tenant['daily_limit']??0?></div></div>
</div></div>
<?php endif;?>
<?php if($doms):?>
<div class="card">
<h2>🌐 Domains (<?=count($doms)?>)</h2>
<table><tr><th>Domain</th><th>Status</th></tr>
<?php foreach($doms as $d):?><tr><td><b><?=htmlspecialchars($d['domain_name'])?></b></td><td><span class="nt <?=$d['verification_status']==='Verified'?'nt-g':'nt-a'?>"><?=$d['verification_status']?></span></td></tr><?php endforeach;?>
</table></div>
<?php endif;?>
</div></body></html>
<?php exit;} // end drill-down
// === LIST MODE ===
$_total=(int)$db->query("SELECT COUNT(*) FROM office_accounts")->fetchColumn();
$_active=(int)$db->query("SELECT COUNT(*) FROM office_accounts WHERE LOWER(status)='active'")->fetchColumn();
$_warming=(int)$db->query("SELECT COUNT(*) FROM office_accounts WHERE LOWER(status)='warming'")->fetchColumn();
$_suspended=(int)$db->query("SELECT COUNT(*) FROM office_accounts WHERE LOWER(status) IN ('suspended','blocked')")->fetchColumn();
$_domains=(int)$db->query("SELECT COUNT(*) FROM office_domains")->fetchColumn();
$_dom_v=(int)$db->query("SELECT COUNT(*) FROM office_domains WHERE verification_status='Verified'")->fetchColumn();
$_tenants=(int)$db->query("SELECT COUNT(*) FROM graph_tenants")->fetchColumn();
// OPUS3-ALL-TENANTS
$_all_tenants=(int)$db->query("SELECT COUNT(DISTINCT tenant_domain) FROM office_accounts WHERE tenant_domain IS NOT NULL AND tenant_domain != '' ")->fetchColumn();
$_tenant_list=$db->query("SELECT tenant_domain, COUNT(*) as accounts, SUM(domains_count) as total_domains, MAX(domains_count) as max_dom FROM office_accounts WHERE tenant_domain IS NOT NULL AND tenant_domain != '' GROUP BY tenant_domain ORDER BY accounts DESC LIMIT 100")->fetchAll();
$_sends=(int)$db->query("SELECT COUNT(*) FROM graph_send_log")->fetchColumn();
$_exchange=(int)$db->query("SELECT COUNT(*) FROM office_accounts WHERE exchange_configured=true")->fetchColumn();
$_by_step=$db->query("SELECT current_step,COUNT(*) as cnt FROM office_accounts GROUP BY current_step ORDER BY current_step")->fetchAll();
// Filters + pagination
$pg=max(1,(int)($_GET['p']??1));$pp=50;$off=($pg-1)*$pp;
$q=$_GET['q']??'';$sf=$_GET['sf']??'';$stf=$_GET['stf']??'';
$w=[];$prm=[];
if($q){$w[]="(name ILIKE :q OR tenant_domain ILIKE :q)";$prm[':q']="%$q%";}
if($sf!==''){$w[]="current_step=:sf";$prm[':sf']=(int)$sf;}
if($stf){$w[]="LOWER(status)=:stf";$prm[':stf']=strtolower($stf);}
$wh=$w?"WHERE ".implode(" AND ",$w):"";
$st=$db->prepare("SELECT id,name,tenant_domain,LOWER(status) as status,current_step,exchange_configured,domains_count,has_license FROM office_accounts $wh ORDER BY id DESC LIMIT $pp OFFSET $off");
$st->execute($prm);$accs=$st->fetchAll();
$st2=$db->prepare("SELECT COUNT(*) FROM office_accounts $wh");$st2->execute($prm);
$filt=(int)$st2->fetchColumn();$pages=max(1,ceil($filt/$pp));
$_top_tenants=$db->query("SELECT tenant_domain,status,users_count,sends_today,daily_limit FROM graph_tenants ORDER BY users_count DESC LIMIT 12")->fetchAll();
$_dom_list=$db->query("SELECT d.domain_name,d.verification_status,a.name as account_name FROM office_domains d LEFT JOIN office_accounts a ON d.account_id=a.id ORDER BY d.verification_status,d.domain_name LIMIT 50")->fetchAll();
?><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVADS — Office Workflow v2</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
:root{--bg:#060a14;--s:#0c1220;--s2:#111827;--b:#1e293b;--t:#e2e8f0;--d:#64748b;--cy:#22d3ee;--gn:#34d399;--am:#fbbf24;--rd:#f87171;--pu:#a78bfa;--bl:#60a5fa}
*{margin:0;padding:0;box-sizing:border-box}body{background:var(--bg);color:var(--t);font-family:'DM Sans',sans-serif;font-size:12px}
.app{max-width:1440px;margin:0 auto;padding:16px}
.hdr{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:var(--s);border:1px solid var(--b);border-radius:10px;margin-bottom:16px}
.hdr h1{font-size:20px;font-weight:700}.hdr h1 b{color:var(--bl)}.hdr .sub{color:var(--d);font-size:11px;margin-top:2px}
.sr{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:16px}
.sc{background:var(--s);border:1px solid var(--b);border-radius:8px;padding:14px;text-align:center}
.sc .n{font-family:'JetBrains Mono',monospace;font-size:20px;font-weight:700}.sc .l{font-size:9px;color:var(--d);margin-top:4px;text-transform:uppercase;letter-spacing:.5px}
.tabs{display:flex;gap:4px;margin-bottom:12px;border-bottom:1px solid var(--b);padding-bottom:6px}
.tab{padding:8px 16px;cursor:pointer;font-weight:600;font-size:11px;color:var(--d);border-bottom:2px solid transparent;transition:.2s}.tab:hover{color:var(--t)}.tab.on{color:var(--bl);border-color:var(--bl)}
.tab .bg{background:rgba(96,165,250,.15);color:var(--bl);padding:1px 8px;border-radius:10px;font-size:9px;margin-left:4px}
.sec{display:none}.sec.on{display:block}
.cd{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:16px;margin-bottom:12px}
table{width:100%;border-collapse:collapse}th{text-align:left;padding:6px 8px;color:var(--d);font-size:9px;text-transform:uppercase;border-bottom:1px solid var(--b);white-space:nowrap}
td{padding:6px 8px;border-bottom:1px solid rgba(30,41,59,.3);font-size:11px}tr:hover{background:rgba(96,165,250,.03)}
.nt{display:inline-block;padding:2px 6px;border-radius:4px;font-size:9px;font-weight:600}
.nt-g{background:rgba(52,211,153,.15);color:var(--gn)}.nt-r{background:rgba(248,113,113,.15);color:var(--rd)}.nt-a{background:rgba(251,191,36,.15);color:var(--am)}.nt-b{background:rgba(96,165,250,.15);color:var(--bl)}.nt-p{background:rgba(167,139,250,.15);color:var(--pu)}
.bar{height:8px;border-radius:4px;background:var(--s2);overflow:hidden;min-width:80px}.bar-fill{height:100%;border-radius:4px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.pipeline{display:flex;gap:4px;align-items:stretch;flex-wrap:wrap;margin:16px 0}
.pipe-step{text-align:center;padding:10px 6px;background:var(--s);border:1px solid var(--b);border-radius:6px;min-width:80px;flex:1}
.pipe-step .n{font-family:'JetBrains Mono',monospace;font-size:16px;font-weight:700}.pipe-step .l{font-size:8px;color:var(--d);margin-top:2px}
.pipe-arr{color:var(--d);font-size:14px;display:flex;align-items:center}
.bb{padding:3px 8px;font-size:8px;border-radius:3px;cursor:pointer;border:1px solid var(--b);background:var(--s2);color:var(--cy);margin-top:6px;transition:.2s;display:inline-block}.bb:hover{background:var(--cy);color:var(--bg)}
.filter-bar{display:flex;gap:10px;align-items:center;margin-bottom:12px;padding:10px 14px;background:var(--s);border:1px solid var(--b);border-radius:8px}
.filter-bar input,.filter-bar select{background:var(--s2);border:1px solid var(--b);color:var(--t);padding:6px 10px;border-radius:4px;font-size:11px;font-family:'DM Sans',sans-serif}
.filter-bar input{flex:1}.filter-bar select{min-width:100px}
.pager{display:flex;gap:6px;justify-content:center;margin:12px 0}.pager a{padding:4px 10px;background:var(--s);border:1px solid var(--b);border-radius:4px;color:var(--bl);text-decoration:none;font-size:11px}.pager a.on{background:var(--bl);color:#fff}
.toast{position:fixed;top:20px;right:20px;background:var(--gn);color:#000;padding:10px 20px;border-radius:8px;font-weight:600;z-index:999;animation:fo 4s forwards}@keyframes fo{0%,70%{opacity:1}100%{opacity:0}}
.drill-link{color:var(--cy);text-decoration:none;cursor:pointer}.drill-link:hover{text-decoration:underline}
@media(max-width:1000px){.sr{grid-template-columns:repeat(3,1fr)}.grid2{grid-template-columns:1fr}.pipeline{flex-direction:column}}
</style>
<link rel="stylesheet" href="wevads-global.css?v=<?=time()?>">
</head><body>
<?php if($msg):?><div class="toast"><?=htmlspecialchars($msg)?></div><?php endif;?>
<div class="app">
<div class="hdr"><div><h1>🏢 <b>Office</b> Workflow v2</h1><div class="sub">O365 accounts • Graph API tenants • Domains verification • Exchange pipeline — <b>Click account ID to drill-down</b></div></div>
<div style="text-align:right"><div style="font-family:'JetBrains Mono',monospace;font-size:28px;font-weight:700;color:var(--bl)"><?=number_format($_total)?></div><div style="font-size:10px;color:var(--d)">Office Accounts</div></div></div>
<div class="sr">
<div class="sc"><div class="n" style="color:var(--gn)"><?=$_active?></div><div class="l">Active</div></div>
<div class="sc"><div class="n" style="color:var(--am)"><?=$_warming?></div><div class="l">Warming</div></div>
<div class="sc"><div class="n" style="color:var(--rd)"><?=$_suspended?></div><div class="l">Susp/Blocked</div></div>
<div class="sc"><div class="n" style="color:var(--cy)"><?=$_dom_v?>/<?=$_domains?></div><div class="l">Domains Verified</div></div>
<div class="sc"><div class="n" style="color:var(--pu)"><?=$_all_tenants?></div><div class="l">Tenants (Office)</div></div>
<div class="sc"><div class="n" style="color:var(--bl)"><?=number_format($_sends)?></div><div class="l">Graph Sends</div></div>
</div>
<div class="cd"><h3 style="margin-bottom:8px">📊 Account Pipeline — 8 Steps <span style="font-weight:400;color:var(--d);font-size:11px">( click Batch to advance all accounts at a step )</span></h3>
<div class="pipeline">
<?php foreach($SN as $i=>$sn):$cnt=0;foreach($_by_step as $s)if((int)$s['current_step']==$i)$cnt=(int)$s['cnt'];$clr=$i<3?'var(--am)':($i<6?'var(--cy)':'var(--gn)');?>
<div class="pipe-step"><div class="n" style="color:<?=$clr?>"><?=$cnt?></div><div class="l">Step <?=$i?>: <?=$sn?></div>
<?php if($i<7&&$cnt>0):?><form method="post"><input type="hidden" name="act" value="batch_advance"><input type="hidden" name="bs" value="<?=$i?>">
<button type="submit" class="bb" onclick="return confirm('Avancer <?=$cnt?> comptes Step <?=$i?> → Step <?=($i+1)?>: <?=$SN[$i+1]?>?')">▶ Batch →<?=$i+1?></button></form><?php endif;?>
<a href="?sf=<?=$i?>" class="bb" style="color:var(--bl);border-color:var(--bl);margin-top:2px">🔍 Filtrer</a>
</div>
<?php if($i<7):?><div class="pipe-arr">→</div><?php endif;endforeach;?>
</div></div>
<div class="filter-bar">
<form method="get" style="display:flex;gap:8px;width:100%;align-items:center">
<input type="text" name="q" placeholder="🔍 Search name, tenant..." value="<?=htmlspecialchars($q)?>">
<select name="sf"><option value="">All Steps</option><?php for($i=0;$i<8;$i++):?><option value="<?=$i?>"<?=$sf!=''&&(int)$sf==$i?' selected':''?>>Step <?=$i?>: <?=$SN[$i]?></option><?php endfor;?></select>
<select name="stf"><option value="">All Status</option><?php foreach(['active','warming','suspended','blocked','pending'] as $s):?><option value="<?=$s?>"<?=$stf===$s?' selected':''?>><?=ucfirst($s)?></option><?php endforeach;?></select>
<button type="submit" class="bb" style="padding:6px 14px;font-size:10px">🔍</button>
<a href="office-workflow.php" class="bb" style="padding:6px 14px;font-size:10px;color:var(--rd)">✕</a>
</form>
<div style="white-space:nowrap;color:var(--d);font-size:10px">Page <?=$pg?>/<?=$pages?> (<?=$filt?> résultats)</div>
</div>
<div class="tabs">
<div class="tab on" onclick="st('acc',this)">Accounts <span class="bg"><?=$filt?></span></div>
<div class="tab" onclick="st('ten',this)">Tenants <span class="bg"><?=$_all_tenants?></span></div>
<div class="tab" onclick="st('dom',this)">Domains <span class="bg"><?=$_domains?></span></div>
<div class="tab" onclick="st('sts',this)">Status</div>
</div>
<div class="sec on" id="s-acc"><div class="cd">
<table><tr><th>#</th><th>Name</th><th>Tenant</th><th>Status</th><th>Step</th><th>Exchange</th><th>Domains</th><th>License</th><th>Actions</th></tr>
<?php foreach($accs as $a):$sc=$a['status'];$nc=$sc==='active'?'nt-g':($sc==='warming'?'nt-a':($sc==='suspended'||$sc==='blocked'?'nt-r':'nt-b'));?>
<tr><td><a href="?account_id=<?=$a['id']?>" class="drill-link"><b><?=$a['id']?></b></a></td>
<td><b><?=htmlspecialchars(substr($a['name']??'',0,30))?></b></td>
<td style="font-size:10px;color:var(--d)"><?=htmlspecialchars(substr($a['tenant_domain']??'',0,25))?></td>
<td><span class="nt <?=$nc?>"><?=ucfirst($sc)?></span></td>
<td style="text-align:center"><?=$a['current_step']?>/7</td>
<td><?=$a['exchange_configured']?'<span class="nt nt-g">Yes</span>':'<span class="nt nt-r">No</span>'?></td>
<td style="text-align:center"><?=$a['domains_count']??0?></td>
<td><?=$a['has_license']?'<span class="nt nt-g">✓</span>':'<span class="nt nt-r">✗</span>'?></td>
<td>
<?php if($a['current_step']<7):?><form method="post" style="display:inline"><input type="hidden" name="aid" value="<?=$a['id']?>"><input type="hidden" name="act" value="advance"><button class="bb" title="Avancer step">▶</button></form><?php endif;?>
<a href="?account_id=<?=$a['id']?>" class="bb" style="color:var(--bl)" title="Drill-down">🔍</a>
</td></tr>
<?php endforeach;?></table>
<?php if($pages>1):?><div class="pager"><?php
$qs=http_build_query(array_filter(['q'=>$q,'sf'=>$sf,'stf'=>$stf]));
for($i=max(1,$pg-3);$i<=min($pages,$pg+3);$i++):?><a href="?p=<?=$i?>&<?=$qs?>"<?=$i==$pg?' class="on"':''?>><?=$i?></a><?php endfor;?></div><?php endif;?>
</div></div>
<div class="sec" id="s-ten"><div class="cd"><h3 style="margin-bottom:10px;color:var(--pu)">Graph API Tenants</h3>
<p style="color:var(--d);margin-bottom:8px"><?=$_all_tenants?> tenants uniques dans office_accounts</p>
<table><tr><th>Tenant</th><th>Comptes</th><th>Domains</th><th>Max/compte</th></tr>
<?php foreach($_tenant_list as $tl):?>
<tr><td class="mono"><?=$tl["tenant_domain"]?></td><td><?=$tl["accounts"]?></td><td><?=$tl["total_domains"]?:0?></td><td><?=$tl["max_dom"]?:0?></td></tr>
<?php endforeach;?>
</table><hr style="border-color:var(--b);margin:16px 0">
<h3 style="margin-bottom:10px;color:var(--gn)">Graph API Tenants (configurés)</h3>
<table><tr><th>Tenant</th><th>Status</th><th>Users</th><th>Sent Today</th><th>Daily Limit</th><th>Usage</th></tr>
<?php foreach($_top_tenants as $t):$pct=($t['daily_limit']??0)>0?round(($t['sends_today']??0)/($t['daily_limit'])*100):0;?>
<tr><td><b><?=htmlspecialchars($t['tenant_domain'])?></b></td>
<td><span class="nt <?=$t['status']==='active'?'nt-g':'nt-r'?>"><?=ucfirst($t['status'])?></span></td>
<td style="font-weight:700;color:var(--cy)"><?=$t['users_count']?></td>
<td><?=$t['sends_today']??0?></td><td><?=$t['daily_limit']??0?></td>
<td><div class="bar"><div class="bar-fill" style="width:<?=min($pct,100)?>%;background:<?=$pct>80?'var(--rd)':($pct>50?'var(--am)':'var(--gn)')?>"></div></div></td>
</tr><?php endforeach;?></table></div></div>
<div class="sec" id="s-dom"><div class="cd"><h3 style="margin-bottom:10px;color:var(--cy)">Office Domains — <?=$_dom_v?> Verified / <?=$_domains?> Total</h3>
<table><tr><th>Domain</th><th>Status</th><th>Account</th></tr>
<?php foreach($_dom_list as $d):?>
<tr><td><b><?=htmlspecialchars($d['domain_name'])?></b></td>
<td><span class="nt <?=$d['verification_status']==='Verified'?'nt-g':'nt-a'?>"><?=$d['verification_status']?></span></td>
<td style="color:var(--d);font-size:10px"><?=htmlspecialchars(substr($d['account_name']??'',0,30))?></td></tr>
<?php endforeach;?></table></div></div>
<div class="sec" id="s-sts"><div class="grid2">
<div class="cd"><h3 style="margin-bottom:10px">By Status</h3>
<table><tr><th>Status</th><th>Count</th><th>Share</th></tr>
<?php $by_st=$db->query("SELECT LOWER(status) as status,COUNT(*) as cnt FROM office_accounts GROUP BY LOWER(status) ORDER BY cnt DESC")->fetchAll();
foreach($by_st as $s):$pct=$_total>0?round($s['cnt']/$_total*100,1):0;$nc=$s['status']==='active'?'nt-g':($s['status']==='warming'?'nt-a':'nt-r');?>
<tr><td><span class="nt <?=$nc?>"><?=ucfirst($s['status'])?></span></td>
<td style="font-weight:700"><?=$s['cnt']?></td>
<td><div class="bar" style="width:120px"><div class="bar-fill" style="width:<?=$pct?>%;background:var(--bl)"></div></div> <?=$pct?>%</td></tr>
<?php endforeach;?></table></div>
<div class="cd"><h3 style="margin-bottom:10px">Key Metrics</h3>
<table><tr><th>Metric</th><th>Value</th></tr>
<tr><td>Total Accounts</td><td style="font-weight:700"><?=number_format($_total)?></td></tr>
<tr><td>Exchange Configured</td><td style="color:<?=$_exchange>0?'var(--gn)':'var(--rd)'?>;font-weight:700"><?=$_exchange?></td></tr>
<tr><td>Graph API Sends</td><td style="color:var(--bl);font-weight:700"><?=number_format($_sends)?></td></tr>
<tr><td>Domains Verified</td><td style="color:var(--gn);font-weight:700"><?=$_dom_v?></td></tr>
<tr><td>Domains Pending</td><td style="color:var(--am);font-weight:700"><?=$_domains-$_dom_v?></td></tr>
</table></div></div></div>
</div>
<script>function st(id,el){document.querySelectorAll('.tab').forEach(t=>t.classList.remove('on'));document.querySelectorAll('.sec').forEach(s=>s.classList.remove('on'));el.classList.add('on');document.getElementById('s-'+id).classList.add('on');}</script>
<?php include("/opt/wevads-arsenal/public/universal-drill.html"); ?>
</body></html>