<?php
/**
 * Same-origin proxy for TikTok Events API (CAPI).
 * Reads per-store config from Firebase RTDB path:
 * clients/{clientId}/siteSettings/tiktokConfig
 *
 * Requires:
 * - api/firebase-rtdb-admin.php
 * - api/firebase-admin-bootstrap.local.php
 * - api/firebase-service-account.local.json (path from bootstrap file)
 */
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']) : '';
$eventName = isset($body['event_name']) ? trim((string) $body['event_name']) : '';
$eventId = isset($body['event_id']) ? trim((string) $body['event_id']) : '';
$eventTime = isset($body['event_time']) && is_numeric($body['event_time']) ? (int) $body['event_time'] : time();
$eventSourceUrl = isset($body['event_source_url']) ? trim((string) $body['event_source_url']) : '';
$customData = isset($body['custom_data']) && is_array($body['custom_data']) ? $body['custom_data'] : [];
$userData = isset($body['user_data']) && is_array($body['user_data']) ? $body['user_data'] : [];
$testEventCodeBody = isset($body['test_event_code']) ? trim((string) $body['test_event_code']) : '';

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 ($eventName === '') {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'event_name is 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'];

$cfgPath = 'clients/' . $clientId . '/siteSettings/tiktokConfig';
$cfgSnap = firebase_rtdb_get($dbUrl, $cfgPath, $access);
if (isset($cfgSnap['error'])) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Could not load TikTok config from Firebase.'], JSON_UNESCAPED_UNICODE);
    exit;
}
$cfg = $cfgSnap['data'];
if (!is_array($cfg) || empty($cfg['enabled'])) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'TikTok tracking is not enabled for this store.'], JSON_UNESCAPED_UNICODE);
    exit;
}

$pixelId = isset($cfg['pixelId']) ? trim((string) $cfg['pixelId']) : '';
$accessToken = isset($cfg['accessToken']) ? trim((string) $cfg['accessToken']) : '';
$testEventCodeCfg = isset($cfg['testEventCode']) ? trim((string) $cfg['testEventCode']) : '';
if ($pixelId === '' || $accessToken === '') {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'TikTok Pixel ID or Access Token missing in settings.'], JSON_UNESCAPED_UNICODE);
    exit;
}

// TikTok supports standard events plus sanitized custom names (e.g. Elite / Aspiring / Scroll50). Never downgrade unknown → PageView.
$sanitizedEvent = trim((string) $eventName);
if (!preg_match('/^[A-Za-z][A-Za-z0-9_]{0,63}$/', $sanitizedEvent)) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'event_name must be 1–64 chars (letter, digit, underscore; must start with a letter).'], JSON_UNESCAPED_UNICODE);
    exit;
}
$eventName = $sanitizedEvent;
// Client may still send Meta-style "Purchase"; TikTok expects CompletePayment.
if ($eventName === 'Purchase') {
    $eventName = 'CompletePayment';
}
if ($eventId === '') {
    $eventId = 'sb_' . strtolower($eventName) . '_' . time() . '_' . substr(md5((string) mt_rand()), 0, 8);
}

$contextUser = [];
if (!empty($userData['external_id'])) $contextUser['external_id'] = (string) $userData['external_id'];
if (!empty($userData['client_user_agent'])) $contextUser['user_agent'] = (string) $userData['client_user_agent'];
if (!empty($userData['client_ip_address'])) $contextUser['ip'] = (string) $userData['client_ip_address'];

$contextPage = [];
if ($eventSourceUrl !== '') $contextPage['url'] = $eventSourceUrl;

$payload = [
    'pixel_code' => $pixelId,
    'event' => $eventName,
    'event_id' => $eventId,
    'timestamp' => (string) $eventTime,
    'context' => [
        'page' => $contextPage,
        'user' => $contextUser,
    ],
    'properties' => $customData,
];
$testCode = $testEventCodeBody !== '' ? $testEventCodeBody : $testEventCodeCfg;
if ($testCode !== '') {
    $payload['test_event_code'] = $testCode;
}

$url = 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/';
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Access-Token: ' . $accessToken,
    ],
    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 TikTok API.'], JSON_UNESCAPED_UNICODE);
    exit;
}

$decoded = json_decode($res, true);
$ok = is_array($decoded) && ((isset($decoded['code']) && (int) $decoded['code'] === 0) || (isset($decoded['message']) && stripos((string) $decoded['message'], 'success') !== false));
if (!$ok) {
    http_response_code($http >= 400 ? $http : 400);
    echo json_encode([
        'status' => 'error',
        'message' => is_array($decoded) && isset($decoded['message']) ? (string) $decoded['message'] : 'TikTok API rejected event.',
        'response' => $decoded ?: null
    ], JSON_UNESCAPED_UNICODE);
    exit;
}

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