'error','message'=>'DB error']);exit;} pg_query($db,"SET search_path TO admin"); switch($action){ case 'stats': $r1=pg_query($db,"SELECT COUNT(*) as total, COUNT(*) FILTER(WHERE is_active=true) as active, COUNT(DISTINCT country_code) as countries, COUNT(DISTINCT network_id) as networks FROM admin.affiliate_offers"); $s=pg_fetch_assoc($r1); $r2=pg_query($db,"SELECT COUNT(*) as c FROM admin.affiliate_networks WHERE status='active'"); $n=pg_fetch_assoc($r2); $r3=pg_query($db,"SELECT SUM(revenue) as rev, SUM(conversions) as conv FROM admin.affiliate_offers"); $p=pg_fetch_assoc($r3); echo json_encode(['status'=>'success','data'=>[ 'total_offers'=>(int)$s['total'], 'active_offers'=>(int)$s['active'], 'countries'=>(int)$s['countries'], 'networks'=>(int)$n['c'], 'total_revenue'=>round((float)$p['rev'],2), 'total_conversions'=>(int)$p['conv'] ]]);break; case 'offers': case 'list': $where=[]; if(!empty($_GET['country']))$where[]="country_code='".pg_escape_string($db,$_GET['country'])."'"; if(!empty($_GET['network']))$where[]="network_id=".(int)$_GET['network']; if(!empty($_GET['vertical']))$where[]="vertical='".pg_escape_string($db,$_GET['vertical'])."'"; if(!empty($_GET['search']))$where[]="offer_name ILIKE '%".pg_escape_string($db,$_GET['search'])."%'"; $w=$where?"WHERE ".implode(' AND ',$where):''; $r=pg_query($db,"SELECT ao.id, ao.offer_name, ao.country_code, ao.vertical, ao.payout, ao.payout_currency, ao.status, ao.tracking_url, ao.landing_page, ao.clicks, ao.conversions, ao.revenue, an.name as network_name FROM admin.affiliate_offers ao LEFT JOIN admin.affiliate_networks an ON ao.network_id=an.id $w ORDER BY ao.payout DESC, ao.offer_name LIMIT 50"); $rows=[];while($row=pg_fetch_assoc($r))$rows[]=$row; echo json_encode(['status'=>'success','data'=>$rows]);break; case 'networks': $r=pg_query($db,"SELECT an.id, an.name, an.api_url, an.status, an.last_sync, an.sync_enabled, COUNT(ao.id) as offer_count FROM admin.affiliate_networks an LEFT JOIN admin.affiliate_offers ao ON an.id=ao.network_id GROUP BY an.id ORDER BY an.name"); $rows=[];while($row=pg_fetch_assoc($r))$rows[]=$row; echo json_encode(['status'=>'success','data'=>$rows]);break; case 'countries': $r=pg_query($db,"SELECT country_code, COUNT(*) as cnt, AVG(payout) as avg_payout FROM admin.affiliate_offers WHERE is_active=true GROUP BY country_code ORDER BY cnt DESC"); $rows=[];while($row=pg_fetch_assoc($r))$rows[]=$row; echo json_encode(['status'=>'success','data'=>$rows]);break; case 'sync': $nid=(int)($_GET['network_id']??$_POST['network_id']??0); $r=pg_query($db,"SELECT * FROM admin.affiliate_networks WHERE id=$nid AND status='active'"); $net=pg_fetch_assoc($r); if(!$net){echo json_encode(['status'=>'error','message'=>'Network not found']);break;} if($net['name']=='Double M'||strpos($net['api_url'],'eflow')!==false){ $ch=curl_init($net['api_url'].'/v1/affiliates/alloffers'); curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>1,CURLOPT_HTTPHEADER=>["X-Eflow-API-Key: ".$net['api_key']]]); $resp=curl_exec($ch);curl_close($ch); $data=json_decode($resp,true); $offers=$data['offers']??[]; $imported=0; foreach($offers as $o){ $oid=pg_escape_string($db,$o['network_offer_id']??''); $oname=pg_escape_string($db,$o['name']??''); $cc='';if(preg_match('/^([A-Z]{2})\s*-/',$o['name']??'',$m))$cc=$m[1]; $vert='sweepstakes';if(stripos($oname,'CPL')!==false)$vert='finance'; $track=pg_escape_string($db,$o['tracking_url']??''); $prev=pg_escape_string($db,$o['preview_url']??''); $st=$o['offer_status']??'active'; pg_query($db,"INSERT INTO admin.affiliate_offers(offer_id,network_id,offer_name,country_code,vertical,tracking_url,landing_page,status,is_active) VALUES('$oid',$nid,'$oname','$cc','$vert','$track','$prev','$st',true) ON CONFLICT DO NOTHING"); $imported++; } pg_query($db,"UPDATE admin.affiliate_networks SET last_sync=NOW() WHERE id=$nid"); echo json_encode(['status'=>'success','message'=>"Sync Double M: $imported offres importées"]); } else { echo json_encode(['status'=>'success','message'=>'Sync lancé pour '.$net['name']]); } break; default: echo json_encode(['status'=>'success','endpoints'=>['stats','offers','networks','countries','sync']]); }