<?php

declare(strict_types=1);

namespace BotGuard\Services\Detection\Modules;

use BotGuard\Services\Detection\ModuleResult;
use BotGuard\Services\Detection\SignalBag;

/**
 * Mouse-movement analysis module.
 *
 * The client summarises pointer telemetry (movement count, speed mean/variance,
 * path curvature/straightness, click timing variance). Human cursors are noisy:
 * variable speed, curved trajectories, jittery click intervals. Scripted pointers
 * move in straight lines at constant speed, or not at all. Touch devices legitimately
 * produce little mouse data, so absence is treated as neutral rather than damning.
 */
final class MouseModule extends AbstractModule
{
    public function key(): string
    {
        return 'mouse';
    }

    public function analyze(SignalBag $signals): ModuleResult
    {
        $mouse = $signals->clientArray('mouse');
        $touch = (bool) ($signals->client('fingerprint.touch_support') ?? false);

        // On touch devices, little/no mouse data is expected — stay neutral.
        if ($mouse === []) {
            return $this->scored($touch ? 0.6 : 0.2, [], $touch ? [] : ['No mouse activity recorded'], ['present' => false, 'touch' => $touch]);
        }

        $moveCount = (int) ($mouse['move_count'] ?? 0);
        $speedStd = (float) ($mouse['speed_stddev'] ?? 0);
        $straightness = (float) ($mouse['straightness'] ?? 1.0); // 1 = perfectly straight
        $curvature = (float) ($mouse['avg_curvature'] ?? 0);
        $clickCount = (int) ($mouse['click_count'] ?? 0);
        $intervalStd = (float) ($mouse['click_interval_stddev'] ?? 0);

        $this->detail('move_count', $moveCount);
        $this->detail('speed_stddev', $speedStd);
        $this->detail('straightness', $straightness);

        // Enough samples to judge.
        $this->check('Sufficient mouse samples', $moveCount >= 10, 1.5);

        // Variable speed (humans accelerate/decelerate).
        $this->check('Variable pointer speed', $speedStd > 0.01, 2.0);

        // Non-linear path (bots often move in straight lines).
        $this->check('Curved movement path', $straightness < 0.99 || $curvature > 0.0, 2.0);

        // Click timing jitter when there were clicks.
        $this->check('Natural click timing', $clickCount === 0 || $intervalStd > 0.0, 1.0);

        return $this->result();
    }
}
