$name, 'channels_launched'=>[]]; // 1. YouTube video generation (async) if (!empty($channels['youtube'])) { // Find or create trend $trend_id = null; if ($angle) { $k = pg_escape_string($db, $angle); pg_query($db, "INSERT INTO yt_trends(keyword,trend_score,country_code,source) VALUES('$k',99,'FR','manual_campaign') ON CONFLICT DO NOTHING"); $t = pg_fetch_assoc(pg_query($db, "SELECT id FROM yt_trends WHERE keyword='$k' ORDER BY id DESC LIMIT 1")); $trend_id = $t['id'] ?? null; } if ($trend_id) { // Generate script via HAMID $prompt = urlencode("YouTube script about: $angle. Style: educational. 180s. French."); $hamid = json_decode(@file_get_contents("http://127.0.0.1:5821/api/hamid-brain.php?action=generate&prompt=$prompt"), true); $script = pg_escape_string($db, $hamid['response'] ?? $hamid['text'] ?? "Script about $angle"); $job_id = pg_fetch_result(pg_query($db, "SELECT gen_random_uuid()"), 0); pg_query($db, "INSERT INTO yt_jobs(id, trend_id, script_text, title, status) VALUES('$job_id', $trend_id, '$script', '$k', 'pending')"); pg_query($db, "UPDATE yt_trends SET processed=true WHERE id=$trend_id"); $results['channels_launched']['youtube'] = ['job_id'=>$job_id, 'status'=>'queued_for_render']; } } // 2. Social Ads campaign if (!empty($channels['ads'])) { $platform = $channels['ads']['platform'] ?? 'all'; $camp_id = pg_fetch_result(pg_query($db, "SELECT gen_random_uuid()"), 0); pg_query($db, "INSERT INTO xc_campaigns(id,campaign_name,platform_target,offer_link,budget_daily,roas_target,status) VALUES('$camp_id','$name','$platform','$offer_link',$budget,".($channels['ads']['roas_target']??2.0).",'draft')"); $results['channels_launched']['ads'] = ['campaign_id'=>$camp_id, 'platform'=>$platform, 'budget'=>$budget]; } // 3. Email (trigger existing unified-send) if (!empty($channels['email'])) { $email_config = $channels['email']; $results['channels_launched']['email'] = [ 'status'=>'ready', 'config_id'=>$email_config['config_id'] ?? null, 'list_id'=>$email_config['list_id'] ?? null, 'note'=>'Call brain_unified_send.php with these params' ]; } // 4. SMS if (!empty($channels['sms'])) { $results['channels_launched']['sms'] = [ 'status'=>'ready', 'provider'=>$channels['sms']['provider'] ?? 'twilio', 'note'=>'Call sms-api.php with campaign params' ]; } // 5. Create cross-channel sync record $yt_jid = $results['channels_launched']['youtube']['job_id'] ?? null; $ads_cid = $results['channels_launched']['ads']['campaign_id'] ?? null; if ($yt_jid || $ads_cid) { pg_query($db, "INSERT INTO xc_content_sync(yt_job_id, ads_campaign_id, content_angle, sync_status) VALUES(".($yt_jid?"'$yt_jid'":"NULL").", ".($ads_cid?"'$ads_cid'":"NULL").", '$angle', 'synced')"); } echo json_encode(['status'=>'success', 'multichannel'=>$results]); break; case 'sync_yt_to_ads': // After YT video renders, auto-create ad creative from it $yt_job_id = pg_escape_string($db, $_POST['yt_job_id'] ?? ''); $job = pg_fetch_assoc(pg_query($db, "SELECT * FROM yt_jobs WHERE id='$yt_job_id' AND status='rendered'")); if (!$job) { echo json_encode(['error'=>'No rendered job']); break; } // Create creative from YT content $cid = pg_fetch_result(pg_query($db, "SELECT gen_random_uuid()"), 0); $titles = "'{\"".pg_escape_string($db,$job['title'])."\",\"Decouvrez ".pg_escape_string($db,substr($job['title'],0,80))."\"}'"; $descs = "'{\"".pg_escape_string($db,substr($job['script_text']??'',0,200))."\"}'"; $media = $job['youtube_url'] ? "'{\"".pg_escape_string($db,$job['youtube_url'])."\"}'":"'{}'"; pg_query($db, "INSERT INTO ads_creatives(id,title_variations,description_variations,media_urls,media_type,source_yt_job_id,source_type) VALUES('$cid',$titles,$descs,$media,'video','$yt_job_id','youtube_auto')"); // Link to any pending ads campaign $sync = pg_fetch_assoc(pg_query($db, "SELECT ads_campaign_id FROM xc_content_sync WHERE yt_job_id='$yt_job_id' AND ads_campaign_id IS NOT NULL LIMIT 1")); if ($sync) { pg_query($db, "UPDATE xc_campaigns SET creative_id='$cid', youtube_url='".pg_escape_string($db,$job['youtube_url']??'')."' WHERE id='{$sync['ads_campaign_id']}'"); } echo json_encode(['status'=>'success', 'creative_id'=>$cid]); break; case 'performance': // Cross-channel performance aggregation $days = (int)($_GET['days'] ?? 7); $yt = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as total, COUNT(*) FILTER(WHERE status='published') as pub, COALESCE(SUM(views_count),0) as views FROM yt_jobs WHERE created_at > NOW()-interval '$days days'")); $ads = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as total, COALESCE(SUM(budget_spent),0) as spent, COALESCE(SUM(revenue_generated),0) as rev, COALESCE(SUM(conversions),0) as conv FROM xc_campaigns WHERE created_at > NOW()-interval '$days days'")); $email = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as sent FROM unified_send_log WHERE created_at > NOW()-interval '$days days'")); $arb = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as total, COUNT(*) FILTER(WHERE decision_type='kill') as kills, COUNT(*) FILTER(WHERE decision_type='boost') as boosts FROM ads_arbitrage_log WHERE executed_at > NOW()-interval '$days days'")); $total_spent = (float)($ads['spent']??0); $total_rev = (float)($ads['rev']??0); echo json_encode(['status'=>'success','period_days'=>$days,'channels'=>[ 'youtube'=>$yt, 'ads'=>$ads, 'email'=>['sent'=>$email['sent']??0], 'arbitrage'=>$arb ],'totals'=>['spent'=>$total_spent,'revenue'=>$total_rev,'roas'=>$total_spent>0?round($total_rev/$total_spent,2):0]]); break; case 'health': // System health check $checks = []; $checks['db'] = pg_ping($db) ? 'ok' : 'fail'; $checks['ffmpeg'] = trim(shell_exec('which ffmpeg 2>/dev/null')) ? 'ok' : 'missing'; $checks['hamid'] = @file_get_contents('http://127.0.0.1:5821/api/hamid-brain.php?action=status') ? 'ok' : 'fail'; $checks['yt_pending'] = (int)pg_fetch_result(pg_query($db, "SELECT COUNT(*) FROM yt_jobs WHERE status='pending'"),0); $checks['ads_active'] = (int)pg_fetch_result(pg_query($db, "SELECT COUNT(*) FROM xc_campaigns WHERE status IN ('active','boosted')"),0); $checks['trends_today'] = (int)pg_fetch_result(pg_query($db, "SELECT COUNT(*) FROM yt_trends WHERE scraped_at::date=CURRENT_DATE"),0); $checks['disk_free_gb'] = round(disk_free_space('/') / 1073741824, 1); $overall = ($checks['db']==='ok' && $checks['ffmpeg']==='ok') ? 'healthy' : 'degraded'; echo json_encode(['status'=>$overall, 'checks'=>$checks, 'timestamp'=>date('c')]); break; } ?>