exec('SET search_path TO admin, public'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo json_encode(['error' => 'DB: ' . $e->getMessage()]); exit; } $input = json_decode(file_get_contents('php://input'), true) ?: $_REQUEST; $action = $input['action'] ?? $_GET['action'] ?? 'status'; switch ($action) { case 'offers': $category = $input['category'] ?? $_GET['category'] ?? null; $q = "SELECT * FROM arbitrage_offers WHERE status = 'active'"; if ($category) $q .= " AND category = '" . preg_replace('/[^a-z]/', '', $category) . "'"; $q .= " ORDER BY epc DESC"; $offers = $pdo->query($q)->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['offers' => $offers, 'count' => count($offers)]); break; case 'add_offer': $network = $input['network'] ?? ''; $name = $input['offer_name'] ?? ''; $offerId = $input['offer_id'] ?? ''; $category = $input['category'] ?? ''; $country = $input['country'] ?? 'FR'; $epc = $input['epc'] ?? 0; $payout = $input['payout'] ?? 0; if (empty($name) || empty($network)) { echo json_encode(['error' => 'network and offer_name required']); exit; } $pdo->prepare("INSERT INTO arbitrage_offers (network,offer_name,offer_id,category,country,epc,payout,last_epc_update) VALUES (?,?,?,?,?,?,?,NOW())") ->execute([$network, $name, $offerId, $category, $country, $epc, $payout]); echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]); break; case 'update_epc': $id = $input['id'] ?? 0; $newEpc = $input['epc'] ?? 0; $convRate = $input['conversion_rate'] ?? null; if (!$id) { echo json_encode(['error' => 'offer id required']); exit; } $q = "UPDATE arbitrage_offers SET epc = ?, last_epc_update = NOW()"; $params = [$newEpc]; if ($convRate !== null) { $q .= ", conversion_rate = ?"; $params[] = $convRate; } $q .= " WHERE id = ?"; $params[] = $id; $pdo->prepare($q)->execute($params); echo json_encode(['success' => true, 'offer_id' => $id, 'new_epc' => $newEpc]); break; case 'recommend': $segment = $input['segment'] ?? $_GET['segment'] ?? 'FR'; $hour = (int)date('G'); // Get best offer for this segment/time $stmt = $pdo->prepare("SELECT * FROM arbitrage_offers WHERE country = ? AND status = 'active' AND auto_pivot = true ORDER BY epc DESC LIMIT 3"); $stmt->execute([$segment]); $top = $stmt->fetchAll(PDO::FETCH_ASSOC); // Time-based weighting (gambling better at night, insurance during day) foreach ($top as &$o) { $timeBonus = 0; if ($o['category'] === 'gambling' && ($hour >= 20 || $hour <= 2)) $timeBonus = 0.5; if ($o['category'] === 'insurance' && $hour >= 9 && $hour <= 18) $timeBonus = 0.3; if ($o['category'] === 'finance' && $hour >= 10 && $hour <= 16) $timeBonus = 0.4; $o['adjusted_epc'] = round((float)$o['epc'] + $timeBonus, 4); $o['time_bonus'] = $timeBonus; } usort($top, function($a, $b) { return $b['adjusted_epc'] <=> $a['adjusted_epc']; }); $recommended = $top[0] ?? null; if ($recommended) { echo json_encode([ 'recommended' => $recommended, 'alternatives' => array_slice($top, 1), 'segment' => $segment, 'hour' => $hour, 'reason' => "Best EPC for {$segment} at {$hour}h: {$recommended['offer_name']} ({$recommended['adjusted_epc']})" ]); } else { echo json_encode(['error' => 'No offers for segment ' . $segment]); } break; case 'pivot': $fromId = $input['from_offer'] ?? 0; $segment = $input['segment'] ?? 'FR'; // Get current best $stmt = $pdo->prepare("SELECT * FROM arbitrage_offers WHERE country = ? AND status = 'active' AND id != ? ORDER BY epc DESC LIMIT 1"); $stmt->execute([$segment, $fromId]); $better = $stmt->fetch(PDO::FETCH_ASSOC); if ($better) { $oldStmt = $pdo->prepare("SELECT * FROM arbitrage_offers WHERE id = ?"); $oldStmt->execute([$fromId]); $old = $oldStmt->fetch(PDO::FETCH_ASSOC); $epcDiff = round((float)$better['epc'] - (float)($old['epc'] ?? 0), 4); $pdo->prepare("INSERT INTO arbitrage_decisions (offer_id, old_offer_id, segment, reason, epc_diff) VALUES (?,?,?,?,?)") ->execute([$better['id'], $fromId, $segment, "Auto-pivot: {$better['offer_name']} EPC {$better['epc']} > old EPC " . ($old['epc'] ?? 0), $epcDiff]); echo json_encode(['pivoted' => true, 'new_offer' => $better, 'epc_gain' => $epcDiff, 'segment' => $segment]); } else { echo json_encode(['pivoted' => false, 'reason' => 'No better offer found']); } break; case 'decisions': $decisions = $pdo->query("SELECT d.*, o.offer_name, o.network FROM arbitrage_decisions d LEFT JOIN arbitrage_offers o ON d.offer_id = o.id ORDER BY d.decided_at DESC LIMIT 20")->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['decisions' => $decisions]); break; case 'stats': $offers = $pdo->query("SELECT COUNT(*) as total, COUNT(DISTINCT network) as networks, COUNT(DISTINCT category) as categories, ROUND(AVG(epc),4) as avg_epc, MAX(epc) as best_epc, ROUND(SUM(payout),2) as total_payout_potential FROM arbitrage_offers WHERE status='active'")->fetch(PDO::FETCH_ASSOC); $decisions = $pdo->query("SELECT COUNT(*) as total_pivots, ROUND(AVG(epc_diff),4) as avg_gain, COUNT(*) FILTER (WHERE decided_at >= CURRENT_DATE) as today FROM arbitrage_decisions")->fetch(PDO::FETCH_ASSOC); $topOffers = $pdo->query("SELECT offer_name, network, epc, payout, category FROM arbitrage_offers WHERE status='active' ORDER BY epc DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['offers' => $offers, 'decisions' => $decisions, 'top_offers' => $topOffers]); break; default: echo json_encode(['status' => 'online', 'service' => 'Conversion Arbitrage Bot', 'version' => '1.0', 'actions' => ['offers','add_offer','update_epc','recommend','pivot','decisions','stats']]); }