setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(Exception $e) { die(json_encode(['error'=>$e->getMessage()])); } $input = json_decode(file_get_contents('php://input'),true) ?: ($_POST ?: $_GET); $action = $input['action'] ?? 'dashboard'; switch($action) { case 'dashboard': $pool = $db->query("SELECT status, COUNT(*) as c FROM admin.domains_pool GROUP BY status ORDER BY c DESC")->fetchAll(PDO::FETCH_ASSOC); $providers = $db->query("SELECT provider, COUNT(*) as c FROM admin.domains_pool GROUP BY provider ORDER BY c DESC")->fetchAll(PDO::FETCH_ASSOC); $office = intval($db->query("SELECT COUNT(DISTINCT split_part(admin_email,'@',2)) FROM admin.office_accounts WHERE status='active'")->fetchColumn()); $tracking = $db->query("SELECT COUNT(*) FROM admin.tracking_domains")->fetchColumn(); $total = $db->query("SELECT COUNT(*) FROM admin.domains_pool")->fetchColumn(); $dns_ok = $db->query("SELECT COUNT(*) FROM admin.domains_pool WHERE dns_complete=true")->fetchColumn(); echo json_encode([ 'total_domains' => intval($total), 'dns_complete' => intval($dns_ok), 'by_status' => $pool, 'by_provider' => $providers, 'office_domains_active' => $office, 'tracking_domains' => intval($tracking), 'health' => intval($total) > 100 ? 'EXCELLENT' : (intval($total) > 10 ? 'GOOD' : 'LOW'), 'integration' => [ 'cloudflare' => intval($db->query("SELECT COUNT(*) FROM admin.domains_pool WHERE zone_id IS NOT NULL AND zone_id!=''")->fetchColumn()), 'freedns' => intval($db->query("SELECT COUNT(*) FROM admin.domains_pool WHERE freedns_account_id IS NOT NULL")->fetchColumn()), 'office365' => intval($db->query("SELECT COUNT(*) FROM admin.domains_pool WHERE provider='office365'")->fetchColumn()), ] ]); break; case 'select_for_send': // Brain-aware domain selection for sending $method = $input['method'] ?? 'o365_smtp'; $isp = $input['isp'] ?? ''; $exclude = $input['exclude_domains'] ?? []; if(strpos($method,'o365') !== false) { // Get O365 domain + matching active account $sql = "SELECT dp.domain, oa.admin_email, oa.admin_password, oa.tenant_id FROM admin.domains_pool dp JOIN admin.office_accounts oa ON oa.id=dp.office_account_id WHERE dp.status='ASSIGNED' AND dp.provider='office365' AND oa.status='active'"; if(!empty($exclude)) { $placeholders = implode(',', array_fill(0, count($exclude), '?')); $sql .= " AND dp.domain NOT IN ($placeholders)"; } $sql .= " ORDER BY RANDOM() LIMIT 1"; $st = $db->prepare($sql); $st->execute($exclude ?: []); $d = $st->fetch(PDO::FETCH_ASSOC); } else { // PMTA / other: get any available domain $d = $db->query("SELECT domain FROM admin.domains_pool WHERE status IN ('FREE','active','ACTIVE') ORDER BY RANDOM() LIMIT 1")->fetch(PDO::FETCH_ASSOC); } // Get matching persona $persona = $db->query("SELECT first_name,last_name,email,country FROM admin.personas WHERE is_active=true ORDER BY RANDOM() LIMIT 1")->fetch(PDO::FETCH_ASSOC); echo json_encode([ 'domain' => $d ?? null, 'persona' => $persona, 'from_address' => ($persona && $d) ? strtolower($persona['first_name'].'.'.$persona['last_name']).'@'.($d['domain']??'') : ($d['email']??null), 'method' => $method ]); break; case 'rotation_pool': // Get N domains for batch sending (rotation) $count = min(intval($input['count'] ?? 10), 50); $method = $input['method'] ?? 'o365_smtp'; if(strpos($method,'o365') !== false) { $domains = $db->query("SELECT dp.domain, oa.admin_email, oa.admin_password, oa.tenant_id FROM admin.domains_pool dp JOIN admin.office_accounts oa ON oa.id=dp.office_account_id WHERE dp.status='ASSIGNED' AND oa.status='active' ORDER BY RANDOM() LIMIT $count")->fetchAll(PDO::FETCH_ASSOC); } else { $domains = $db->query("SELECT domain FROM admin.domains_pool WHERE status IN ('FREE','active','ACTIVE') ORDER BY RANDOM() LIMIT $count")->fetchAll(PDO::FETCH_ASSOC); } // Get matching personas $personas = $db->query("SELECT first_name,last_name,email,country FROM admin.personas WHERE is_active=true ORDER BY RANDOM() LIMIT $count")->fetchAll(PDO::FETCH_ASSOC); echo json_encode([ 'domains' => $domains, 'personas' => $personas, 'count' => count($domains), 'method' => $method ]); break; case 'sync_inventory': // Sync domains_pool stats into domain_inventory for backward compatibility $db->exec("DELETE FROM admin.domain_inventory"); $db->exec("INSERT INTO admin.domain_inventory(name,status,registrar,dns_provider,created_at) SELECT domain, CASE WHEN status='ASSIGNED' THEN 'active' WHEN status='FREE' THEN 'available' ELSE lower(status) END, CASE WHEN provider='office365' THEN 'namecheap' ELSE 'cloudflare' END, CASE WHEN zone_id IS NOT NULL AND zone_id!='' THEN 'cloudflare' ELSE 'manual' END, COALESCE(created_at, NOW()) FROM admin.domains_pool WHERE status IN ('ASSIGNED','FREE','active','ACTIVE') ON CONFLICT DO NOTHING"); $synced = $db->query("SELECT COUNT(*) FROM admin.domain_inventory")->fetchColumn(); echo json_encode(['synced'=>intval($synced),'status'=>'ok']); break; case 'health_check': // Full pipeline health check $checks = []; // Domain pool $dp = intval($db->query("SELECT COUNT(*) FROM admin.domains_pool")->fetchColumn()); $checks['domain_pool'] = ['count'=>$dp, 'status'=>$dp>100?'OK':'LOW']; // O365 accounts linked to domains $linked = intval($db->query("SELECT COUNT(*) FROM admin.office_accounts oa WHERE oa.status='active' AND EXISTS(SELECT 1 FROM admin.domains_pool dp WHERE oa.id=dp.office_account_id)")->fetchColumn()); $total_o365 = intval($db->query("SELECT COUNT(*) FROM admin.office_accounts WHERE status='active'")->fetchColumn()); $checks['o365_domain_link'] = ['linked'=>$linked, 'total'=>$total_o365, 'status'=>$linked>0?'OK':'BROKEN']; // Personas $personas = intval($db->query("SELECT COUNT(*) FROM admin.personas WHERE is_active=true")->fetchColumn()); $checks['personas'] = ['count'=>$personas, 'status'=>$personas>=20?'OK':'LOW']; // Brain configs $winners = intval($db->query("SELECT COUNT(*) FROM admin.brain_send_configs WHERE is_winner=true")->fetchColumn()); $checks['brain_winners'] = ['count'=>$winners, 'status'=>$winners>5?'OK':'LOW']; // Tracking $tracking = intval($db->query("SELECT COUNT(*) FROM admin.tracking_domains")->fetchColumn()); $checks['tracking'] = ['count'=>$tracking, 'status'=>$tracking>0?'OK':'MISSING']; // Send methods $methods = intval($db->query("SELECT COUNT(*) FROM admin.send_methods WHERE is_active=true")->fetchColumn()); $checks['send_methods'] = ['active'=>$methods, 'status'=>$methods>2?'OK':'LOW']; // Cloud providers $clouds = intval($db->query("SELECT COUNT(*) FROM admin.cloud_providers WHERE is_active=true")->fetchColumn()); $checks['cloud_providers'] = ['count'=>$clouds, 'status'=>$clouds>5?'OK':'LOW']; // N8N $n8n = @file_get_contents("http://127.0.0.1:5678/healthz"); $checks['n8n'] = ['status'=>$n8n!==false?'OK':'DOWN']; // PMTA $pmta = @fsockopen('127.0.0.1', 25, $en, $es, 2); $checks['pmta'] = ['status'=>$pmta?'OK':'DOWN']; if($pmta) fclose($pmta); $all_ok = !in_array('BROKEN', array_column($checks, 'status')) && !in_array('DOWN', array_column($checks, 'status')); echo json_encode([ 'pipeline_status' => $all_ok ? 'PRODUCTION_READY' : 'NEEDS_FIX', 'checks' => $checks, 'timestamp' => date('c') ]); break; case 'providers': // List all domain registrar/DNS integrations echo json_encode([ 'cloudflare' => [ 'domains' => intval($db->query("SELECT COUNT(*) FROM admin.domains_pool WHERE zone_id IS NOT NULL AND zone_id!=''")->fetchColumn()), 'api' => 'https://api.cloudflare.com/client/v4/', 'actions' => ['dns_sync','zone_create','dns_add','dns_verify'] ], 'freedns' => [ 'domains' => intval($db->query("SELECT COUNT(*) FROM admin.domains_pool WHERE freedns_account_id IS NOT NULL")->fetchColumn()), 'api' => 'https://freedns.afraid.org/api/', 'actions' => ['subdomain_create','dns_update'] ], 'namecheap' => [ 'domains' => intval($db->query("SELECT COUNT(*) FROM admin.namecheap_domains")->fetchColumn()), 'api' => 'https://api.namecheap.com/xml.response', 'actions' => ['domain_purchase','dns_set','whois_guard'] ], 'office365' => [ 'domains' => intval($db->query("SELECT COUNT(*) FROM admin.domains_pool WHERE provider='office365'")->fetchColumn()), 'actions' => ['domain_verify','mx_setup','autodiscover','dkim_enable'] ], 'n8n_workflows' => [ 'dns_sync_cloudflare' => 'active', 'freedns_auto_creator' => 'active', 'o365_full_setup' => 'active' ] ]); break; default: echo json_encode(['actions'=>['dashboard','select_for_send','rotation_pool','sync_inventory','health_check','providers']]); } ?>