<?php
/**
 * Same-origin proxy for Meta Conversions API — Purchase events only.
 * Reads per-store config from Firebase RTDB:
 *   clients/{clientId}/siteSettings (pixelId + facebookConfig)
 *
 * Requires same bootstrap as tiktok-events-proxy.php:
 * - api/firebase-rtdb-admin.php
 * - api/firebase-admin-bootstrap.local.php
 * - Service account JSON
 */
header('Content-Type: application/json; charset=UTF-8');

require_once __DIR__ . '/firebase-rtdb-admin.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['status' => 'error', 'message' => 'Method not allowed'], JSON_UNESCAPED_UNICODE);
    exit;
}

$raw = file_get_contents('php://input');
$body = json_decode($raw !== false && $raw !== '' ? $raw : '{}', true);
if (!is_array($body)) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Invalid JSON'], JSON_UNESCAPED_UNICODE);
    exit;
}

$clientId = isset($body['clientId']) ? trim((string) $body['clientId']) : '';
$orderKey = isset($body['orderKey']) ? trim((string) $body['orderKey']) : '';
$eventId = isset($body['eventId']) ? trim((string) $body['eventId']) : '';
$eventSourceUrl = isset($body['eventSourceUrl']) ? trim((string) $body['eventSourceUrl']) : '';
$value = isset($body['value']) ? (float) $body['value'] : 0.0;
$currency = isset($body['currency']) ? strtoupper(trim((string) $body['currency'])) : 'BDT';
$items = isset($body['items']) && is_array($body['items']) ? $body['items'] : [];
$customer = isset($body['customer']) && is_array($body['customer']) ? $body['customer'] : [];
$fbp = isset($body['fbp']) ? trim((string) $body['fbp']) : '';
$fbc = isset($body['fbc']) ? trim((string) $body['fbc']) : '';
$clientUserAgent = isset($body['client_user_agent']) ? trim((string) $body['client_user_agent']) : '';
$clientIp = isset($body['client_ip_address']) ? trim((string) $body['client_ip_address']) : '';

if ($clientId === '' || !preg_match('/^[-A-Za-z0-9_]{1,128}$/', $clientId)) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Valid clientId is required.'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($orderKey === '' || $eventId === '') {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'orderKey and eventId are required.'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($value <= 0 || $currency === '' || strlen($currency) > 8) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'value and currency are required.'], JSON_UNESCAPED_UNICODE);
    exit;
}
if (!function_exists('curl_init')) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'PHP curl extension is required.'], JSON_UNESCAPED_UNICODE);
    exit;
}

$bootPath = __DIR__ . '/firebase-admin-bootstrap.local.php';
if (!is_readable($bootPath)) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Server not configured. Copy api/firebase-admin-bootstrap.example.php to firebase-admin-bootstrap.local.php.'], JSON_UNESCAPED_UNICODE);
    exit;
}
$boot = include $bootPath;
if (!is_array($boot)) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Invalid firebase-admin-bootstrap.local.php.'], JSON_UNESCAPED_UNICODE);
    exit;
}

$saPath = isset($boot['service_account_json_path']) ? trim((string) $boot['service_account_json_path']) : '';
$dbUrl = isset($boot['firebase_database_url']) ? trim((string) $boot['firebase_database_url']) : '';
if ($saPath === '' || $dbUrl === '') {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Bootstrap missing service account path or database URL.'], JSON_UNESCAPED_UNICODE);
    exit;
}

$tok = firebase_service_account_access_token($saPath);
if (isset($tok['error'])) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Firebase admin error: ' . $tok['error']], JSON_UNESCAPED_UNICODE);
    exit;
}
$access = $tok['access_token'];

$settingsPath = 'clients/' . $clientId . '/siteSettings';
$settingsSnap = firebase_rtdb_get($dbUrl, $settingsPath, $access);
if (isset($settingsSnap['error'])) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Could not load site settings from Firebase.'], JSON_UNESCAPED_UNICODE);
    exit;
}
$site = $settingsSnap['data'];
if (!is_array($site)) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Invalid site settings.'], JSON_UNESCAPED_UNICODE);
    exit;
}

$pixelId = isset($site['pixelId']) ? trim((string) $site['pixelId']) : '';
$fbCfg = isset($site['facebookConfig']) && is_array($site['facebookConfig']) ? $site['facebookConfig'] : [];
$graphToken = isset($fbCfg['accessToken']) ? trim((string) $fbCfg['accessToken']) : '';
$capiEnabled = !array_key_exists('capiEnabled', $fbCfg) || $fbCfg['capiEnabled'] !== false;

if (!$capiEnabled) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Facebook CAPI is disabled for this store.'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($pixelId === '' || !preg_match('/^\d{15,16}$/', $pixelId)) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Facebook Pixel ID is not configured.'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($graphToken === '') {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Facebook access token missing in settings.'], JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * @return string|null sha256 hex or null
 */
function sb_meta_hash_norm($s)
{
    $s = (string) $s;
    $s = function_exists('mb_strtolower') ? trim(mb_strtolower($s, 'UTF-8')) : trim(strtolower($s));
    if ($s === '') {
        return null;
    }
    return hash('sha256', $s);
}

/**
 * @return string|null sha256 hex or null
 */
function sb_meta_hash_phone($phone)
{
    $d = preg_replace('/\D+/', '', (string) $phone);
    if (strlen($d) === 11 && isset($d[0]) && $d[0] === '0') {
        $d = '880' . substr($d, 1);
    }
    if ($d === '') {
        return null;
    }
    return hash('sha256', $d);
}

$userData = [];
if ($clientUserAgent !== '') {
    $userData['client_user_agent'] = substr($clientUserAgent, 0, 4096);
}
if ($clientIp !== '' && preg_match('/^[\d.:a-fA-F]{7,45}$/', $clientIp)) {
    $userData['client_ip_address'] = $clientIp;
}
if ($fbp !== '') {
    $userData['fbp'] = substr($fbp, 0, 256);
}
if ($fbc !== '') {
    $userData['fbc'] = substr($fbc, 0, 256);
}

$phone = isset($customer['phone']) ? (string) $customer['phone'] : '';
$name = isset($customer['name']) ? (string) $customer['name'] : '';
$phHash = sb_meta_hash_phone($phone);
if ($phHash) {
    $userData['ph'] = [$phHash];
}
$fnHash = sb_meta_hash_norm($name);
if ($fnHash) {
    $userData['fn'] = [$fnHash];
}

$contents = [];
foreach ($items as $it) {
    if (!is_array($it)) {
        continue;
    }
    $pid = isset($it['id']) ? trim((string) $it['id']) : '';
    if ($pid === '') {
        continue;
    }
    $qty = isset($it['quantity']) ? (int) $it['quantity'] : 1;
    $price = isset($it['price']) ? (float) $it['price'] : 0.0;
    $contents[] = [
        'id' => substr($pid, 0, 128),
        'quantity' => max(1, $qty),
        'item_price' => $price,
    ];
}

$customData = [
    'value' => round($value, 2),
    'currency' => $currency,
    'content_type' => 'product',
    'contents' => $contents,
];

$event = [
    'event_name' => 'Purchase',
    'event_time' => time(),
    'event_id' => substr($eventId, 0, 120),
    'action_source' => 'website',
    'event_source_url' => $eventSourceUrl !== '' ? substr($eventSourceUrl, 0, 1024) : null,
    'user_data' => $userData,
    'custom_data' => $customData,
];
if ($event['event_source_url'] === null) {
    unset($event['event_source_url']);
}

$graphBody = json_encode(['data' => [$event]], JSON_UNESCAPED_UNICODE);
$url = 'https://graph.facebook.com/v19.0/' . rawurlencode($pixelId) . '/events?access_token=' . rawurlencode($graphToken);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $graphBody,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$res = curl_exec($ch);
$errno = curl_errno($ch);
$http = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($errno !== 0 || $res === false) {
    http_response_code(502);
    echo json_encode(['status' => 'error', 'message' => 'Could not reach Meta Graph API.'], JSON_UNESCAPED_UNICODE);
    exit;
}

$decoded = json_decode($res, true);
$ok = $http >= 200 && $http < 300 && is_array($decoded) && empty($decoded['error']);

if (!$ok) {
    $msg = is_array($decoded) && isset($decoded['error']['message']) ? (string) $decoded['error']['message'] : 'Meta rejected or did not accept the event.';
    http_response_code($http >= 400 ? $http : 400);
    echo json_encode([
        'status' => 'error',
        'message' => $msg,
        'response' => $decoded ?: null,
    ], JSON_UNESCAPED_UNICODE);
    exit;
}

echo json_encode([
    'status' => 'success',
    'orderKey' => $orderKey,
    'event_id' => $eventId,
    'provider' => 'facebook_capi',
    'response' => $decoded,
], JSON_UNESCAPED_UNICODE);
