<?php

declare(strict_types=1);

namespace BotGuard\Services\Detection\Modules;

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

/**
 * Request-timing module.
 *
 * Humans take a measurable, variable amount of time to read a page and interact.
 * Bots often submit almost instantly (near-zero time-to-interact / time-to-submit)
 * or, conversely, at suspiciously precise round intervals. This module rewards
 * plausible, non-instant timing.
 */
final class TimingModule extends AbstractModule
{
    public function key(): string
    {
        return 'timing';
    }

    public function analyze(SignalBag $signals): ModuleResult
    {
        $timing = $signals->clientArray('timing');

        if ($timing === []) {
            return $this->scored(0.3, [], ['No timing data'], ['present' => false]);
        }

        $timeOnPage = (int) ($timing['time_on_page_ms'] ?? 0);
        $timeToInteract = (int) ($timing['time_to_interact_ms'] ?? 0);
        $timeToSubmit = (int) ($timing['time_to_submit_ms'] ?? 0);

        $this->detail('time_on_page_ms', $timeOnPage);
        $this->detail('time_to_interact_ms', $timeToInteract);
        $this->detail('time_to_submit_ms', $timeToSubmit);

        // Some dwell before the first interaction (instant = scripted).
        $this->check('Non-instant first interaction', $timeToInteract >= 200, 2.0);

        // Total time on page is human-plausible (not sub-half-second).
        $this->check('Plausible time on page', $timeOnPage >= 500, 1.5);

        // Submit didn't happen faster than a human could click.
        $this->check('Non-instant submit', $timeToSubmit === 0 || $timeToSubmit >= 300, 1.5);

        // Upper sanity bound: absurdly large values suggest a replayed/forged clock.
        $this->check('Timing within sane bounds', $timeOnPage <= 3_600_000, 0.5);

        return $this->result();
    }
}
