<?php

declare(strict_types=1);

namespace BotGuard\Services\Detection\Modules;

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

/**
 * Session analysis module.
 *
 * Uses server-injected session signals (duration, request count, navigation
 * pattern, repeat-visitor flag, integrity token match) to reward coherent
 * sessions and penalise anomalies such as a session with many requests but zero
 * dwell time, or a mismatched integrity token (tampering).
 */
final class SessionModule extends AbstractModule
{
    public function key(): string
    {
        return 'session';
    }

    public function analyze(SignalBag $signals): ModuleResult
    {
        $durationMs = (int) ($signals->client('session.duration_ms') ?? 0);
        $requestCount = (int) ($signals->client('session.request_count') ?? 1);
        $repeatVisitor = (bool) ($signals->client('session.repeat_visitor') ?? false);
        $integrityOk = (bool) ($signals->client('session.integrity_ok') ?? true);
        $navCount = (int) ($signals->client('session.navigation_count') ?? 0);

        $this->detail('duration_ms', $durationMs);
        $this->detail('request_count', $requestCount);
        $this->detail('repeat_visitor', $repeatVisitor);

        // Session integrity token must validate (set by the server on issue).
        $this->check('Session integrity valid', $integrityOk, 3.0);

        // A burst of requests within a near-zero session is bot-like.
        $burst = $requestCount > 15 && $durationMs < 2000;
        $this->check('No request burst', ! $burst, 2.0);

        // Some measurable dwell before acting.
        $this->check('Non-trivial session duration', $durationMs >= 800, 1.5);

        // Repeat visitors (known fingerprint) are more likely human/returning.
        $this->check('Recognised or first-time visitor', true, 0.5); // neutral baseline
        if ($repeatVisitor) {
            $this->detail('note', 'repeat visitor');
        }

        // Reasonable navigation (0-1 on a landing page is normal; huge is odd).
        $this->check('Plausible navigation count', $navCount <= 50, 0.5);

        return $this->result(0.8);
    }
}
