<?php
// File: modules/crawler-logger.php
// Crawler beacon + crawler stats

if ( ! defined('ABSPATH') ) { exit; }

// Shared API-key validation for ALL modules
require_once plugin_dir_path(__FILE__) . '../includes/sac-utils.php';

add_action('rest_api_init', function () {

    // Beacon endpoint is called via <img>. It must be publicly reachable.
    register_rest_route('myaio/v1', '/crawler-beacon', [
        'methods'             => WP_REST_Server::READABLE, // GET
        'callback'            => 'myaio_sac_log_crawler',
        'permission_callback' => 'myaio_sac_rest_permission_check',
    ]);

    // Stats should be protected with the same API key validation
    register_rest_route('myaio/v1', '/crawler-stats', [
        'methods'             => WP_REST_Server::READABLE, // GET
        'callback'            => 'myaio_sac_get_crawler_stats',
        'permission_callback' => 'myaio_sac_rest_permission_check',
        'args'                => [
            'bot' => [
                'required' => false,
                'type'     => 'string',
            ],
        ],
    ]);
});

/**
 * Logs known crawler hits.
 * - Only logs when plugin is verified AND tracker is enabled (opt-in).
 * - Returns a 1x1 gif when requested as an image (so the <img> doesn't break).
 * - Keeps your JSON output for non-image requests.
 */
function myaio_sac_log_crawler( WP_REST_Request $request ) {

    // Tracker must be explicitly enabled
    $enabled  = (bool) get_option('myaio_sac_enable_tracker', 0);
    $verified = (bool) get_option('myaio_sac_api_verified', false);

    if ( ! $enabled || ! $verified ) {
        return myaio_sac_crawler_beacon_response($request, [
            'status'  => 'ignored',
            'message' => 'Tracker disabled or not verified',
        ]);
    }

    $agent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : 'Unknown';
    $ip    = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'Unknown';

    // Prevent oversized option values
    $agent = mb_substr($agent, 0, 255);
    $ip    = mb_substr($ip, 0, 64);

    $bot = myaio_sac_identify_crawler($agent);

    if ($bot === 'Other') {
//         if ( defined( 'WP_DEBUG' ) && WP_DEBUG && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
//     $safe_agent = sanitize_text_field( $agent );
//     $safe_ip    = sanitize_text_field( $ip );

//     error_log( sprintf(
//         '[MYAIO CRAWLER] Unknown User-Agent: %s (IP: %s)',
//         $safe_agent,
//         $safe_ip
//     ) );
// }


        return myaio_sac_crawler_beacon_response($request, [
            'status'  => 'ignored',
            'message' => 'Not a known bot',
            'agent'   => $agent,
            'ip'      => $ip
        ]);
    }

    $now     = current_time('mysql');
    $current = get_option('myaio_sac_crawler_stats', []);

    if (!is_array($current)) {
        $current = [];
    }

    if (!isset($current[$bot])) {
        $current[$bot] = [
            'count'      => 1,
            'last_seen'  => $now,
            'last_ip'    => $ip,
            'last_agent' => $agent
        ];
    } else {
        $current[$bot]['count']      = (int) ($current[$bot]['count'] ?? 0) + 1;
        $current[$bot]['last_seen']  = $now;
        $current[$bot]['last_ip']    = $ip;
        $current[$bot]['last_agent'] = $agent;
    }

    update_option('myaio_sac_crawler_stats', $current);

    return myaio_sac_crawler_beacon_response($request, [
        'status' => 'logged',
        'bot'    => $bot,
        'ip'     => $ip,
        'agent'  => $agent
    ]);
}

/**
 * If request is made as an image (via <img src="...">), return a 1x1 gif.
 * Otherwise return JSON (your existing output).
 */
function myaio_sac_crawler_beacon_response( WP_REST_Request $request, array $json ) {

    $accept = strtolower((string) $request->get_header('accept'));
    $as_img = (strpos($accept, 'image/') !== false);

    if ($as_img) {
        // 1x1 transparent GIF
        $gif = base64_decode('R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');

        $response = new WP_REST_Response($gif, 200);
        $response->header('Content-Type', 'image/gif');
        $response->header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
        $response->header('Pragma', 'no-cache');
        return $response;
    }

    return rest_ensure_response($json);
}

/**
 * Get crawler statistics (optional filter by ?bot=Googlebot)
 * Protected by myaio_sac_rest_permission_check via permission_callback.
 */
function myaio_sac_get_crawler_stats( WP_REST_Request $request ) {
    $stats  = get_option('myaio_sac_crawler_stats', []);
    $filter = $request->get_param('bot');

    if (!is_array($stats)) {
        $stats = [];
    }

    if ($filter && isset($stats[$filter])) {
        return rest_ensure_response(['crawler_stats' => [$filter => $stats[$filter]]]);
    }

    return rest_ensure_response(['crawler_stats' => $stats]);
}

/**
 * Identify crawlers by known user-agent signatures
 */
function myaio_sac_identify_crawler($agent) {
    $bots = [
        'Googlebot'        => 'Googlebot',
        'Googlebot-Mobile' => 'Googlebot-Mobile',
        'Bingbot'          => 'Bingbot',
        'Applebot'         => 'Applebot',
        'DuckDuckBot'      => 'DuckDuckBot',
        'Slurp'            => 'Slurp',
        'YandexBot'        => 'YandexBot',
        'facebook'         => 'facebookexternalhit',
        'Twitterbot'       => 'Twitterbot',
        'AhrefsBot'        => 'AhrefsBot',
        'SemrushBot'       => 'SemrushBot',
        'PetalBot'         => 'PetalBot',
        'Screaming Frog'   => 'Screaming Frog',
        'GTmetrix'         => 'GTmetrix',
        'UptimeRobot'      => 'UptimeRobot'
    ];

    foreach ($bots as $name => $needle) {
        if (stripos((string) $agent, (string) $needle) !== false) {
            return $name;
        }
    }

    return 'Other';
}
