<?php
/**
 * Admin-triggered push campaign sender via Firebase Cloud Messaging HTTP v1.
 * Reads subscribers from RTDB:
 * clients/{clientId}/pushSubscribers
 */
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']);
    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']);
    exit;
}

$clientId = isset($body['clientId']) ? trim((string) $body['clientId']) : '';
$idToken = isset($body['idToken']) ? trim((string) $body['idToken']) : '';
$title = isset($body['title']) ? trim((string) $body['title']) : '';
$message = isset($body['message']) ? trim((string) $body['message']) : '';
$clickUrl = isset($body['clickUrl']) ? trim((string) $body['clickUrl']) : '';
$iconUrl = isset($body['iconUrl']) ? trim((string) $body['iconUrl']) : '';
$audience = isset($body['audience']) ? trim((string) $body['audience']) : 'all';

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.']);
    exit;
}
if ($idToken === '' || $title === '' || $message === '') {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'idToken, title and message are required.']);
    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: firebase-admin-bootstrap.local.php missing.']);
    exit;
}
$boot = include $bootPath;
if (!is_array($boot)) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Invalid firebase-admin-bootstrap.local.php.']);
    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']) : '';
$webKey = isset($boot['firebase_web_api_key']) ? trim((string) $boot['firebase_web_api_key']) : '';
if ($saPath === '' || $dbUrl === '' || $webKey === '' || $webKey === 'PASTE_FIREBASE_WEB_API_KEY_HERE') {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Bootstrap config incomplete.']);
    exit;
}

$verify = firebase_verify_id_token($idToken, $webKey);
if (isset($verify['error'])) {
    http_response_code(401);
    echo json_encode(['status' => 'error', 'message' => $verify['error']]);
    exit;
}
$uid = $verify['uid'];

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

$adminSnap = firebase_rtdb_get($dbUrl, 'clients/' . $clientId . '/admins/' . $uid, $dbAccess);
if (isset($adminSnap['error']) || !firebase_rtdb_is_truthy_admin($adminSnap['data'] ?? null)) {
    http_response_code(403);
    echo json_encode(['status' => 'error', 'message' => 'Forbidden: admin access required.']);
    exit;
}

$subSnap = firebase_rtdb_get($dbUrl, 'clients/' . $clientId . '/pushSubscribers', $dbAccess);
if (isset($subSnap['error'])) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Could not read subscribers.']);
    exit;
}
$subs = is_array($subSnap['data']) ? $subSnap['data'] : [];
$active = [];
$activeMeta = [];
foreach ($subs as $sid => $sub) {
    if (!is_array($sub)) continue;
    if (isset($sub['active']) && $sub['active'] === false) continue;
    $token = isset($sub['token']) ? trim((string) $sub['token']) : '';
    if ($token === '') continue;
    $active[$sid] = $token;
    $activeMeta[$sid] = max(
        isset($sub['updatedAt']) ? (int) $sub['updatedAt'] : 0,
        isset($sub['createdAt']) ? (int) $sub['createdAt'] : 0
    );
}
if ($audience === 'latest' && !empty($active)) {
    arsort($activeMeta);
    $latestSid = array_key_first($activeMeta);
    if ($latestSid !== null && isset($active[$latestSid])) {
        $active = [$latestSid => $active[$latestSid]];
    }
}
if (empty($active)) {
    echo json_encode(['status' => 'success', 'sent' => 0, 'failed' => 0, 'message' => 'No active subscribers.']);
    exit;
}

$sa = json_decode(file_get_contents($saPath), true);
$projectId = isset($sa['project_id']) ? trim((string) $sa['project_id']) : '';
if ($projectId === '') {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'project_id missing in service account JSON.']);
    exit;
}

$fcmTok = firebase_service_account_access_token(
    $saPath,
    'https://www.googleapis.com/auth/firebase.messaging https://www.googleapis.com/auth/cloud-platform'
);
if (isset($fcmTok['error'])) {
    http_response_code(503);
    echo json_encode(['status' => 'error', 'message' => 'Could not obtain FCM access token.']);
    exit;
}
$fcmAccess = $fcmTok['access_token'];

$campaignId = 'cmp_' . time() . '_' . substr(md5((string) mt_rand()), 0, 7);
$sendUrl = 'https://fcm.googleapis.com/v1/projects/' . rawurlencode($projectId) . '/messages:send';
$sent = 0;
$failed = 0;
$errors = [];
$invalid = [];
$defaultIcon = '';
$cfgSnap = firebase_rtdb_get($dbUrl, 'clients/' . $clientId . '/siteSettings/pushConfig', $dbAccess);
if (!isset($cfgSnap['error']) && is_array($cfgSnap['data'])) {
    $defaultIcon = isset($cfgSnap['data']['defaultIconUrl']) ? trim((string) $cfgSnap['data']['defaultIconUrl']) : '';
}
if ($iconUrl === '') $iconUrl = $defaultIcon;
if ($clickUrl === '') $clickUrl = '/';

foreach ($active as $sid => $token) {
    $payload = [
        'message' => [
            'token' => $token,
            'notification' => [
                'title' => $title,
                'body' => $message,
            ],
            'webpush' => [
                'notification' => array_filter([
                    'title' => $title,
                    'body' => $message,
                    'icon' => $iconUrl,
                    'badge' => $iconUrl,
                ]),
                'fcm_options' => [
                    'link' => $clickUrl,
                ],
                'data' => [
                    'campaignId' => $campaignId,
                    'clickUrl' => $clickUrl,
                ],
            ],
            'data' => [
                'campaignId' => $campaignId,
                'clickUrl' => $clickUrl,
            ],
        ]
    ];

    $ch = curl_init($sendUrl);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $fcmAccess,
        ],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 20,
    ]);
    $res = curl_exec($ch);
    $http = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $obj = json_decode((string) $res, true);
    if ($http >= 200 && $http < 300 && is_array($obj) && !empty($obj['name'])) {
        $sent++;
        continue;
    }
    $failed++;
    $errMsg = is_array($obj) && isset($obj['error']['message']) ? (string) $obj['error']['message'] : ('HTTP ' . $http);
    if (count($errors) < 10) $errors[] = ['subscriber' => $sid, 'error' => $errMsg];
    if (strpos($errMsg, 'UNREGISTERED') !== false || strpos($errMsg, 'registration-token-not-registered') !== false || strpos($errMsg, 'INVALID_ARGUMENT') !== false) {
        $invalid[] = $sid;
    }
}

$now = time();
if (!empty($invalid)) {
    foreach ($invalid as $sid) {
        firebase_rtdb_patch($dbUrl, 'clients/' . $clientId . '/pushSubscribers/' . $sid, $dbAccess, [
            'active' => false,
            'lastError' => 'inactive_by_send',
            'updatedAt' => $now * 1000,
        ]);
    }
}

$campaignLog = [
    'campaignId' => $campaignId,
    'title' => $title,
    'message' => $message,
    'clickUrl' => $clickUrl,
    'iconUrl' => $iconUrl,
    'audience' => $audience,
    'sent' => $sent,
    'failed' => $failed,
    'errors' => $errors,
    'createdAt' => $now * 1000,
    'createdBy' => $uid,
];
firebase_rtdb_put($dbUrl, 'clients/' . $clientId . '/pushCampaigns/' . $campaignId, $dbAccess, $campaignLog);

echo json_encode([
    'status' => 'success',
    'campaignId' => $campaignId,
    'sent' => $sent,
    'failed' => $failed,
    'errors' => $errors
], JSON_UNESCAPED_UNICODE);
