<?php

declare(strict_types=1);

namespace App\Framework\Http\Session;

use App\Framework\DateTime\Clock;
use App\Framework\Http\IpAddress;

final readonly class SecurityManager
{
    public function __construct(
        // Muss Privat bleiben: Der SecurityManager ist teil einer übergeordneten Session
        private Session $session,
        private Clock $clock,
        public int $sessionTimeout = 3600,
        public int $sessionRegenerationInterval = 300
    ) {}

    private function key(): string
    {
        return SessionKey::SECURITY->value;
    }

    public function initialize(string $userAgent, IpAddress $ipAddress): void
    {
        $securityData = new SessionSecurityData(
                                            $userAgent,
                                            $ipAddress,
                                            $this->clock->time(),
                                            $this->clock->time()
        );

        $this->session->set($this->key(), $securityData->toArray());
    }

    public function updateLastActivity(): void
    {
        if ($this->session->has($this->key())) {
            $securityData = SessionSecurityData::fromSession($this->session);

            $updatedData = $securityData->withLastActivity($this->clock->time());
            $this->session->set($this->key(), $updatedData->toArray());
        }
    }

    public function shouldRegenerateId(): bool
    {
        if (!$this->session->has($this->key())) {
            return true;
        }

        $securityData = SessionSecurityData::fromSession($this->session);

        return ($this->clock->time() - $securityData->lastRegeneration) > $this->sessionRegenerationInterval;
    }

    public function markRegenerated(): void
    {
        if ($this->session->has($this->key())) {
            $securityData = SessionSecurityData::fromSession($this->session);

            $updatedData = $securityData->withLastRegeneration($this->clock->time());
            $this->session->set($this->key(), $updatedData->toArray());
        }
    }

    public function validate(string $userAgent, IpAddress $ipAddress): bool
    {
        if (!$this->session->has($this->key())) {
            return false;
        }

        $securityData = SessionSecurityData::fromSession($this->session);


        // UserAgent muss übereinstimmen
        if ($securityData->userAgent !== $userAgent) {
            return false;
        }

        // IP-Adressen-Prüfung
        if ($securityData->ipAddress->value !== $ipAddress->value) {
            return false;
        }

        // Timeout-Prüfung
        if (($this->clock->time() - $securityData->lastActivity) > $this->sessionTimeout) {
            return false;
        }

        return true;
    }
}
