<?php
/**
 * index.php — Entry point / router for the WhatsApp Bot webhook
 *
 * Place this file in the web root (e.g., /public_html/ or /www/).
 * It routes all incoming POST requests to the bot handler and
 * provides a simple log viewer for GET requests with ?logs.
 *
 * Webhook URL to set in wifi2fm.com:
 *   https://bankybot.rubickservices.com/
 *   or
 *   https://bankybot.rubickservices.com/index.php
 *
 * NOTE:
 *   The decision (accept/reject) and voucher-check callbacks
 *   ONLY persist data to the database. They DO NOT send any
 *   WhatsApp messages — that responsibility now lives elsewhere.
 */

declare(strict_types=1);

// ─────────────────────────────────────────────────────────────
// Configuration
// ─────────────────────────────────────────────────────────────

// Path to the bot handler (adjust if your directory structure differs)
$botFilePath = __DIR__ . '/whatsapp-bot/bot.php';

// Path to the log file
$logFilePath = __DIR__ . '/whatsapp-bot/storage/whatsapp_bot.log';

// Simple auth token for viewing logs (change this to something secret!)
$logViewToken = 'BankyBot2026';
$botConfigPath = __DIR__ . '/whatsapp-bot/bot.config.json';

function apiResponse(array $data, int $statusCode = 200): void
{
    http_response_code($statusCode);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function loadSyncConfig(string $botConfigPath): array
{
    if (!is_file($botConfigPath)) {
        return [];
    }

    $raw = file_get_contents($botConfigPath);
    if ($raw === false || trim($raw) === '') {
        return [];
    }

    $decoded = json_decode($raw, true);
    return is_array($decoded) ? $decoded : [];
}

function syncDb(array $config): PDO
{
    $name = trim((string) ($config['db_name'] ?? ''));
    if ($name === '') {
        throw new RuntimeException('Missing db_name in bot.config.json');
    }

    $host = (string) ($config['db_host'] ?? '127.0.0.1');
    $port = (string) ($config['db_port'] ?? '3306');
    $user = (string) ($config['db_user'] ?? 'root');
    $pass = (string) ($config['db_pass'] ?? '');

    return new PDO(
        "mysql:host={$host};port={$port};dbname={$name};charset=utf8mb4",
        $user,
        $pass,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]
    );
}

function ensureSyncTablesForApi(PDO $pdo): void
{
    $pdo->exec("CREATE TABLE IF NOT EXISTS `bot_servers` (
        `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        `server_id` VARCHAR(64) NOT NULL,
        `api_token` VARCHAR(128) NOT NULL,
        `instance_id` VARCHAR(80) NOT NULL DEFAULT '',
        `server_name` VARCHAR(120) NOT NULL DEFAULT '',
        `status` ENUM('active','inactive') NOT NULL DEFAULT 'active',
        `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`),
        UNIQUE KEY `uq_server_id` (`server_id`),
        UNIQUE KEY `uq_instance_id` (`instance_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS `bot_server_orders` (
        `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        `order_no` VARCHAR(64) NOT NULL,
        `source_chat_id` VARCHAR(40) NOT NULL,
        `source_server_id` VARCHAR(64) NOT NULL,
        `target_server_id` VARCHAR(64) NOT NULL,
        `payload_json` JSON NOT NULL,
        `api_result_json` JSON NULL,
        `sync_status` ENUM('new','fetched','synced') NOT NULL DEFAULT 'new',
        `fetched_at` DATETIME NULL,
        `synced_at` DATETIME NULL,
        `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`),
        UNIQUE KEY `uq_order_no` (`order_no`),
        KEY `idx_target_status` (`target_server_id`, `sync_status`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS `bot_order_desicon` (
        `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        `order_no` VARCHAR(64) NOT NULL,
        `customer_name` VARCHAR(191) NOT NULL,
        `desicon` ENUM('accept','reject') NOT NULL,
        `reject_reason` TEXT NULL,
        `vouchers_json` JSON NULL,
        `api_payload_json` JSON NOT NULL,
        `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`),
        KEY `idx_order_no` (`order_no`),
        KEY `idx_desicon` (`desicon`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS `bot_voucher_check_requests` (
        `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        `request_no` VARCHAR(64) NOT NULL,
        `chat_id` VARCHAR(40) NOT NULL,
        `source_server_id` VARCHAR(64) NOT NULL,
        `bot_instance_id` VARCHAR(80) NOT NULL DEFAULT '',
        `card_number` VARCHAR(120) NOT NULL,
        `card_password` VARCHAR(120) NOT NULL,
        `request_status` ENUM('pending','submitted','completed','failed') NOT NULL DEFAULT 'pending',
        `result_json` JSON NULL,
        `api_result_json` JSON NULL,
        `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`),
        UNIQUE KEY `uq_voucher_check_request_no` (`request_no`),
        KEY `idx_voucher_check_chat` (`chat_id`),
        KEY `idx_voucher_check_server` (`source_server_id`),
        KEY `idx_voucher_check_status` (`request_status`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    try {
        $pdo->exec("ALTER TABLE `bot_servers` ADD COLUMN `instance_id` VARCHAR(80) NOT NULL DEFAULT '' AFTER `api_token`");
    } catch (Throwable $e) {
    }
    try {
        $pdo->exec("ALTER TABLE `bot_servers` ADD UNIQUE KEY `uq_instance_id` (`instance_id`)");
    } catch (Throwable $e) {
    }
    try {
        $pdo->exec("ALTER TABLE `bot_voucher_check_requests` ADD COLUMN `source_server_id` VARCHAR(64) NOT NULL DEFAULT '' AFTER `chat_id`");
    } catch (Throwable $e) {
    }
    try {
        $pdo->exec("ALTER TABLE `bot_voucher_check_requests` ADD COLUMN `bot_instance_id` VARCHAR(80) NOT NULL DEFAULT '' AFTER `source_server_id`");
    } catch (Throwable $e) {
    }
    try {
        $pdo->exec("ALTER TABLE `bot_voucher_check_requests` ADD KEY `idx_voucher_check_server` (`source_server_id`)");
    } catch (Throwable $e) {
    }
}

function findOrderForDecision(PDO $pdo, string $orderNo): ?array
{
    $dbName = (string) $pdo->query('SELECT DATABASE()')->fetchColumn();

    $stmtTable = $pdo->prepare('SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = ? AND table_name = ?');
    $stmtTable->execute([$dbName, 'bot_orders']);
    $hasBotOrders = ((int) $stmtTable->fetchColumn()) > 0;

    if ($hasBotOrders) {
        $stmt = $pdo->prepare('SELECT `order_no`, `sync_status`, `chat_id` AS `source_chat_id`, `payload_json` FROM `bot_orders` WHERE `order_no` = ? LIMIT 1');
        $stmt->execute([$orderNo]);
        $row = $stmt->fetch();
        if (is_array($row)) {
            return $row;
        }
    }

    $sql = 'SELECT `order_no`, `sync_status`, `source_chat_id`, `payload_json` FROM `bot_server_orders` WHERE `order_no` = ? LIMIT 1';
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$orderNo]);
    $row = $stmt->fetch();

    return is_array($row) ? $row : null;
}

function normalizeVouchers(mixed $vouchers): array
{
    if (is_string($vouchers)) {
        $trimmed = trim($vouchers);
        return $trimmed === '' ? [] : [
            [
                'code' => $trimmed,
                'password' => '',
            ]
        ];
    }

    if (!is_array($vouchers)) {
        return [];
    }

    $normalized = [];
    foreach ($vouchers as $voucher) {
        if (is_string($voucher)) {
            $item = trim($voucher);
            if ($item !== '') {
                $normalized[] = [
                    'code' => $item,
                    'password' => '',
                ];
            }
            continue;
        }

        if (is_numeric($voucher)) {
            $normalized[] = [
                'code' => (string) $voucher,
                'password' => '',
            ];
            continue;
        }

        if (is_array($voucher)) {
            $code = trim((string) ($voucher['code'] ?? $voucher['voucher'] ?? $voucher['name'] ?? $voucher['value'] ?? ''));
            $password = trim((string) ($voucher['password'] ?? $voucher['voucher_password'] ?? $voucher['pass'] ?? ''));
            if ($code !== '') {
                $normalized[] = [
                    'code' => $code,
                    'password' => $password,
                ];
            }
        }
    }

    return $normalized;
}

function normalizeApiCredential(string $value): string
{
    $value = trim($value);
    if ($value === '') {
        return '';
    }

    $decoded = rawurldecode($value);
    if ($decoded !== '') {
        $value = $decoded;
    }

    return trim($value);
}

function getBearerToken(): string
{
    $auth = trim((string) ($_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? ''));
    if ($auth === '' || stripos($auth, 'Bearer ') !== 0) {
        return '';
    }

    return normalizeApiCredential(substr($auth, 7));
}

function validateServerAuth(PDO $pdo, string $serverId, string $token): array
{
    $stmt = $pdo->prepare('SELECT `id`, `server_id`, `api_token`, `status` FROM `bot_servers` WHERE TRIM(`server_id`) = TRIM(?) LIMIT 1');
    $stmt->execute([$serverId]);
    $row = $stmt->fetch();

    if (!is_array($row)) {
        return ['ok' => false, 'reason' => 'server_id_not_found'];
    }

    $dbToken = trim((string) ($row['api_token'] ?? ''));
    if ($dbToken === '' || !hash_equals($dbToken, $token)) {
        return ['ok' => false, 'reason' => 'token_mismatch'];
    }

    $status = strtolower(trim((string) ($row['status'] ?? 'inactive')));
    if ($status !== 'active') {
        return ['ok' => false, 'reason' => 'server_inactive'];
    }

    return ['ok' => true, 'reason' => 'ok'];
}

function fetchOrdersForServer(PDO $pdo, string $serverId, int $limit): array
{
    $sqlTarget = "SELECT `order_no`, `payload_json`, `created_at` FROM `bot_server_orders` WHERE `target_server_id` = ? AND `sync_status` IN ('new','fetched') ORDER BY `id` ASC LIMIT {$limit}";
    $stmt = $pdo->prepare($sqlTarget);
    $stmt->execute([$serverId]);
    $rows = $stmt->fetchAll();

    if (is_array($rows) && count($rows) > 0) {
        return ['rows' => $rows, 'match_mode' => 'target_server_id'];
    }

    // Fallback for same-server polling when legacy rows were inserted with mismatched target_server_id.
    $sqlSource = "SELECT `order_no`, `payload_json`, `created_at` FROM `bot_server_orders` WHERE `source_server_id` = ? AND `sync_status` IN ('new','fetched') ORDER BY `id` ASC LIMIT {$limit}";
    $stmt = $pdo->prepare($sqlSource);
    $stmt->execute([$serverId]);
    $rows = $stmt->fetchAll();

    return ['rows' => is_array($rows) ? $rows : [], 'match_mode' => 'source_server_id_fallback'];
}

function findVoucherCheckRequest(PDO $pdo, string $requestNo): ?array
{
    $stmt = $pdo->prepare('SELECT * FROM `bot_voucher_check_requests` WHERE `request_no` = ? LIMIT 1');
    $stmt->execute([$requestNo]);
    $row = $stmt->fetch();
    return is_array($row) ? $row : null;
}

// ─────────────────────────────────────────────────────────────
// Request Method Detection
// ─────────────────────────────────────────────────────────────

$method = strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET');

if (isset($_GET['api']) && $_GET['api'] === 'orders') {
    try {
        $config = loadSyncConfig($botConfigPath);
        $pdo = syncDb($config);
        ensureSyncTablesForApi($pdo);

        $serverId = normalizeApiCredential((string) ($_GET['server_id'] ?? $_POST['server_id'] ?? $_SERVER['HTTP_X_SERVER_ID'] ?? ''));
        $token = normalizeApiCredential((string) ($_GET['token'] ?? $_POST['token'] ?? $_SERVER['HTTP_X_SERVER_TOKEN'] ?? $_SERVER['HTTP_X_API_TOKEN'] ?? ''));

        if ($token === '') {
            $token = getBearerToken();
        }

        if ($serverId === '' || $token === '') {
            apiResponse([
                'status' => 'error',
                'message' => 'server_id and token are required',
                'hint' => 'Pass credentials in query params, X-Server-ID/X-Server-Token headers, or Authorization: Bearer <token>.',
            ], 422);
        }

        $auth = validateServerAuth($pdo, $serverId, $token);
        if (($auth['ok'] ?? False) !== true) {
            apiResponse([
                'status' => 'error',
                'message' => 'invalid server credentials',
                'reason' => (string) ($auth['reason'] ?? 'unknown'),
                'server_id' => $serverId,
                'token_length' => strlen($token),
            ], 403);
        }

        if ($method === 'POST') {
            $raw = file_get_contents('php://input');
            $body = json_decode($raw ?: '{}', true);
            $orderNos = is_array($body['order_nos'] ?? null) ? $body['order_nos'] : [];

            if ($orderNos !== []) {
                $placeholders = implode(',', array_fill(0, count($orderNos), '?'));
                $params = array_merge(['synced', date('Y-m-d H:i:s'), $serverId, $serverId], array_values($orderNos));
                $stmt = $pdo->prepare("UPDATE `bot_server_orders` SET `sync_status` = ?, `synced_at` = ? WHERE (`target_server_id` = ? OR `source_server_id` = ?) AND `order_no` IN ({$placeholders})");
                $stmt->execute($params);
            }

            apiResponse(['status' => 'success', 'updated' => count($orderNos)]);
        }

        $limit = max(1, min(200, (int) ($_GET['limit'] ?? 50)));
        $fetchResult = fetchOrdersForServer($pdo, $serverId, $limit);
        $rows = (array) ($fetchResult['rows'] ?? []);
        $matchMode = (string) ($fetchResult['match_mode'] ?? 'target_server_id');

        $orders = [];
        $orderNos = [];
        foreach ($rows as $row) {
            $payload = json_decode((string) ($row['payload_json'] ?? '{}'), true);
            if (!is_array($payload)) {
                $payload = [];
            }
            $orders[] = [
                'order_no' => (string) ($row['order_no'] ?? ''),
                'created_at' => (string) ($row['created_at'] ?? ''),
                'payload' => $payload,
            ];
            $orderNos[] = (string) ($row['order_no'] ?? '');
        }

        if ($orderNos !== []) {
            $placeholders = implode(',', array_fill(0, count($orderNos), '?'));
            $stmt = $pdo->prepare("UPDATE `bot_server_orders` SET `sync_status` = ?, `fetched_at` = ? WHERE (`target_server_id` = ? OR `source_server_id` = ?) AND `order_no` IN ({$placeholders})");
            $params = array_merge(['fetched', date('Y-m-d H:i:s'), $serverId, $serverId], $orderNos);
            $stmt->execute($params);
        }

        apiResponse(['status' => 'success', 'server_id' => $serverId, 'match_mode' => $matchMode, 'orders' => $orders]);
    } catch (Throwable $e) {
        apiResponse(['status' => 'error', 'message' => $e->getMessage()], 500);
    }
}

// ─────────────────────────────────────────────────────────────
// Decision callback (accept / reject)
// Persists the decision to DB. DOES NOT send WhatsApp messages.
// ─────────────────────────────────────────────────────────────

if (isset($_GET['api']) && $_GET['api'] === 'order_desicon_callback') {
    try {
        if ($method !== 'POST') {
            apiResponse(['status' => 'error', 'message' => 'method_not_allowed'], 405);
        }

        $config = loadSyncConfig($botConfigPath);
        $pdo = syncDb($config);
        ensureSyncTablesForApi($pdo);

        $raw = file_get_contents('php://input');
        $body = json_decode($raw ?: '{}', true);
        if (!is_array($body)) {
            apiResponse(['status' => 'error', 'message' => 'invalid_json_body'], 422);
        }

        $orderNo = trim((string) ($body['order_no'] ?? $body['order_number'] ?? ''));
        $customerName = trim((string) ($body['customer_name'] ?? ''));
        $desicon = strtolower(trim((string) ($body['desicon'] ?? $body['decision'] ?? '')));
        $rejectReason = trim((string) ($body['reject_reason'] ?? ''));
        $vouchers = normalizeVouchers($body['vouchers'] ?? []);

        if ($orderNo === '' || $customerName === '' || $desicon === '') {
            apiResponse([
                'status' => 'error',
                'message' => 'order_no, customer_name and desicon are required',
            ], 422);
        }

        if (!in_array($desicon, ['accept', 'reject'], true)) {
            apiResponse([
                'status' => 'error',
                'message' => 'desicon must be accept or reject',
            ], 422);
        }

        if ($desicon === 'reject' && $rejectReason === '') {
            apiResponse([
                'status' => 'error',
                'message' => 'reject_reason is required when desicon is reject',
            ], 422);
        }

        $orderRow = findOrderForDecision($pdo, $orderNo);
        if (!is_array($orderRow)) {
            apiResponse([
                'status' => 'error',
                'message' => 'order_not_found_in_bot_orders',
                'order_no' => $orderNo,
            ], 404);
        }

        $syncStatus = strtolower(trim((string) ($orderRow['sync_status'] ?? '')));
        if ($syncStatus !== 'synced') {
            apiResponse([
                'status' => 'error',
                'message' => 'order_must_be_synced_first',
                'order_no' => $orderNo,
                'sync_status' => $syncStatus,
            ], 409);
        }

        // 1) Persist the decision record
        $stmt = $pdo->prepare('INSERT INTO `bot_order_desicon` (`order_no`,`customer_name`,`desicon`,`reject_reason`,`vouchers_json`,`api_payload_json`) VALUES (?,?,?,?,?,?)');
        $stmt->execute([
            $orderNo,
            $customerName,
            $desicon,
            $rejectReason !== '' ? $rejectReason : null,
            json_encode($vouchers, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
            json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
        ]);

        // 2) (No WhatsApp messaging here — handled by an external service.)
        //    We just return the chat_id so the caller knows who the order belongs to.
        $payload = json_decode((string) ($orderRow['payload_json'] ?? '{}'), true);
        if (!is_array($payload)) {
            $payload = [];
        }
        $chatId = trim((string) ($payload['chat_id'] ?? $orderRow['source_chat_id'] ?? ''));

        apiResponse([
            'status' => 'success',
            'order_no' => $orderNo,
            'desicon' => $desicon,
            'chat_id' => $chatId,
            'messages_sent' => 0,
            'note' => 'Decision saved. No WhatsApp messages were sent by the router.',
        ]);
    } catch (Throwable $e) {
        apiResponse(['status' => 'error', 'message' => $e->getMessage()], 500);
    }
}

// ─────────────────────────────────────────────────────────────
// Voucher check callback
// Persists the check result to DB. DOES NOT send WhatsApp messages.
// ─────────────────────────────────────────────────────────────

if (isset($_GET['api']) && $_GET['api'] === 'voucher_check_callback') {
    try {
        if ($method !== 'POST') {
            apiResponse(['status' => 'error', 'message' => 'method_not_allowed'], 405);
        }

        $config = loadSyncConfig($botConfigPath);
        $pdo = syncDb($config);
        ensureSyncTablesForApi($pdo);

        $raw = file_get_contents('php://input');
        $body = json_decode($raw ?: '{}', true);
        if (!is_array($body)) {
            apiResponse(['status' => 'error', 'message' => 'invalid_json_body'], 422);
        }

        $requestNo = trim((string) ($body['request_no'] ?? ''));
        $status = strtolower(trim((string) ($body['status'] ?? 'completed')));
        $cardNumber = trim((string) ($body['card_number'] ?? ''));
        $cardPassword = trim((string) ($body['card_password'] ?? ''));
        $voucherData = $body['voucher'] ?? $body['voucher_data'] ?? null;

        if ($requestNo === '') {
            apiResponse(['status' => 'error', 'message' => 'request_no is required'], 422);
        }

        if (!in_array($status, ['pending', 'submitted', 'completed', 'failed'], true)) {
            apiResponse(['status' => 'error', 'message' => 'status must be pending/submitted/completed/failed'], 422);
        }

        $requestRow = findVoucherCheckRequest($pdo, $requestNo);
        if (!is_array($requestRow)) {
            apiResponse(['status' => 'error', 'message' => 'request_not_found', 'request_no' => $requestNo], 404);
        }

        $chatId = trim((string) ($requestRow['chat_id'] ?? ''));
        if ($chatId === '') {
            apiResponse(['status' => 'error', 'message' => 'chat_id_not_found_for_request', 'request_no' => $requestNo], 422);
        }

        if ($cardNumber === '') {
            $cardNumber = (string) ($requestRow['card_number'] ?? '');
        }
        if ($cardPassword === '') {
            $cardPassword = (string) ($requestRow['card_password'] ?? '');
        }

        // Persist the result. NO WhatsApp messaging here.
        $stmt = $pdo->prepare('UPDATE `bot_voucher_check_requests` SET `card_number` = ?, `card_password` = ?, `request_status` = ?, `result_json` = ?, `api_result_json` = ? WHERE `request_no` = ? LIMIT 1');
        $stmt->execute([
            $cardNumber,
            $cardPassword,
            $status,
            json_encode($voucherData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
            json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
            $requestNo,
        ]);

        apiResponse([
            'status' => 'success',
            'request_no' => $requestNo,
            'chat_id' => $chatId,
            'source_server_id' => (string) ($requestRow['source_server_id'] ?? ''),
            'bot_instance_id' => (string) ($requestRow['bot_instance_id'] ?? ''),
            'request_status' => $status,
            'messages_sent' => 0,
            'note' => 'Voucher check result saved. No WhatsApp messages were sent by the router.',
        ]);
    } catch (Throwable $e) {
        apiResponse(['status' => 'error', 'message' => $e->getMessage()], 500);
    }
}

// ─────────────────────────────────────────────────────────────
// POST → Forward to bot.php (webhook handler)
// ─────────────────────────────────────────────────────────────

if ($method === 'POST') {
    // Log the incoming request for debugging
    $timestamp = date('Y-m-d H:i:s');
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
    $contentLength = $_SERVER['CONTENT_LENGTH'] ?? '0';

    // Ensure storage directory exists
    $storageDir = __DIR__ . '/whatsapp-bot/storage';
    if (!is_dir($storageDir)) {
        @mkdir($storageDir, 0775, true);
    }

    // Log to router log
    $routerLog = "[{$timestamp}] [router] POST from {$ip} UA={$ua} Content-Length={$contentLength}\n";
    @file_put_contents($logFilePath, $routerLog, FILE_APPEND);

    if (!is_file($botFilePath)) {
        // Bot file not found — log error and return 200 (so webhook doesn't retry)
        $errorMsg = "[{$timestamp}] [router] ERROR: bot.php not found at {$botFilePath}\n";
        @file_put_contents($logFilePath, $errorMsg, FILE_APPEND);
        http_response_code(200);
        echo json_encode(['status' => 'error', 'message' => 'Bot handler not found']);
        exit;
    }

    // Include and execute the bot handler
    require $botFilePath;
    exit;
}

// ─────────────────────────────────────────────────────────────
// GET → Health check or log viewer
// ─────────────────────────────────────────────────────────────

// Log viewer: ?logs&token=YOUR_TOKEN
if (isset($_GET['logs'])) {
    $providedToken = trim($_GET['token'] ?? '');

    if ($providedToken !== $logViewToken) {
        http_response_code(403);
        echo '🔒 Access denied. Add ?logs&token=YOUR_TOKEN';
        exit;
    }

    header('Content-Type: text/html; charset=utf-8');

    $lines = [];
    $tailCount = (int) ($_GET['lines'] ?? 100);
    $tailCount = max(10, min($tailCount, 2000));

    if (is_file($logFilePath)) {
        $allLines = file($logFilePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if (is_array($allLines)) {
            $lines = array_slice($allLines, -$tailCount);
        }
    }

    // Filter option
    $filter = trim($_GET['filter'] ?? '');

    if ($filter !== '') {
        $lines = array_filter($lines, fn($line) => stripos($line, $filter) !== false);
        $lines = array_values($lines);
    }

    $escapedLines = array_map('htmlspecialchars', $lines);
    $lineCount = count($lines);
    $fileSize = is_file($logFilePath) ? round(filesize($logFilePath) / 1024, 1) : 0;

    // Build dropdown selected-attribute helpers
    $tailCountSelect50   = $tailCount === 50   ? 'selected' : '';
    $tailCountSelect100  = $tailCount === 100  ? 'selected' : '';
    $tailCountSelect300  = $tailCount === 300  ? 'selected' : '';
    $tailCountSelect500  = $tailCount === 500  ? 'selected' : '';
    $tailCountSelect1000 = $tailCount === 1000 ? 'selected' : '';

    $serverName = htmlspecialchars((string) ($_SERVER['SERVER_NAME'] ?? ''));
    $providedTokenSafe = htmlspecialchars($providedToken);
    $filterSafe = htmlspecialchars($filter);

    echo <<<HTML
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>BankyBot - Log Viewer</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { background: #0d1117; color: #c9d1d9; font-family: 'Courier New', monospace; font-size: 13px; }
        .header { background: #161b22; border-bottom: 1px solid #30363d; padding: 12px 20px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }
        .header h1 { font-size: 16px; color: #58a6ff; }
        .header .info { color: #8b949e; font-size: 12px; }
        .controls { background: #161b22; padding: 10px 20px; border-bottom: 1px solid #30363d; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
        .controls input, .controls select { background: #0d1117; color: #c9d1d9; border: 1px solid #30363d; padding: 6px 10px; border-radius: 4px; font-size: 12px; }
        .controls button { background: #238636; color: #fff; border: none; padding: 6px 14px; border-radius: 4px; cursor: pointer; font-size: 12px; }
        .controls button:hover { background: #2ea043; }
        .controls button.danger { background: #da3633; }
        .controls button.danger:hover { background: #f85149; }
        .log-container { padding: 15px 20px; overflow-x: auto; }
        pre { white-space: pre-wrap; word-wrap: break-word; line-height: 1.6; }
        .line-error { color: #f85149; }
        .line-warn { color: #d29922; }
        .line-ok { color: #3fb950; }
        .line-info { color: #58a6ff; }
        .empty { color: #8b949e; text-align: center; padding: 40px; font-size: 14px; }
        @media (max-width: 600px) { body { font-size: 11px; } .header, .controls, .log-container { padding: 8px 10px; } }
    </style>
</head>
<body>
    <div class="header">
        <h1>🤖 BankyBot WhatsApp Log Viewer</h1>
        <div class="info">Showing last {$lineCount} lines | Log size: {$fileSize} KB | {$serverName}</div>
    </div>
    <div class="controls">
        <form method="get" style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
            <input type="hidden" name="logs" value="">
            <input type="hidden" name="token" value="{$providedTokenSafe}">
            <input type="text" name="filter" value="{$filterSafe}" placeholder="Filter logs..." style="width:200px;">
            <select name="lines">
                <option value="50" {$tailCountSelect50}>50 lines</option>
                <option value="100" {$tailCountSelect100}>100 lines</option>
                <option value="300" {$tailCountSelect300}>300 lines</option>
                <option value="500" {$tailCountSelect500}>500 lines</option>
                <option value="1000" {$tailCountSelect1000}>1000 lines</option>
            </select>
            <button type="submit">🔍 Filter</button>
            <button type="button" onclick="location.reload()">🔄 Refresh</button>
        </form>
    </div>
    <div class="log-container">
HTML;

    if ($lineCount === 0) {
        echo '<div class="empty">📭 No log entries found.</div>';
    } else {
        echo '<pre>';
        foreach ($escapedLines as $line) {
            $cssClass = '';
            if (stripos($line, 'ERROR') !== false || stripos($line, 'FAILED') !== false || stripos($line, 'Fatal') !== false) {
                $cssClass = 'line-error';
            } elseif (stripos($line, 'Warning') !== false || stripos($line, '⚠') !== false) {
                $cssClass = 'line-warn';
            } elseif (stripos($line, 'OK') !== false || stripos($line, '✅') !== false || stripos($line, 'success') !== false) {
                $cssClass = 'line-ok';
            } elseif (stripos($line, '[router]') !== false || stripos($line, '[normalize]') !== false) {
                $cssClass = 'line-info';
            }
            echo $cssClass ? "<span class=\"{$cssClass}\">{$line}</span>\n" : "{$line}\n";
        }
        echo '</pre>';
    }

    echo <<<HTML
    </div>
    <script>
        // Auto-scroll to bottom
        window.scrollTo(0, document.body.scrollHeight);
        // Auto-refresh every 10 seconds
        setTimeout(() => location.reload(), 10000);
    </script>
</body>
</html>
HTML;
    exit;
}

// Default GET — health check
http_response_code(200);
header('Content-Type: application/json');
echo json_encode([
    'status' => 'active',
    'service' => 'BankyBot WhatsApp Webhook',
    'timestamp' => date('c'),
    'tip' => 'Send POST requests to this URL from wifi2fm.com webhook settings.',
]);