<?php

namespace App\Http\Middleware;

use App\Models\SecuritySetting;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use Symfony\Component\HttpFoundation\Response;

class SessionSecurity
{
    protected function getMaxSessions(): int
    {
        return (int) SecuritySetting::getValue('session', 'max_sessions', 3);
    }

    protected function getSessionLifetime(): int
    {
        return (int) SecuritySetting::getValue('session', 'session_lifetime', 120);
    }

    protected function getRegenerateInterval(): int
    {
        return (int) SecuritySetting::getValue('session', 'regenerate_interval', 30);
    }

    public function handle(Request $request, Closure $next): Response
    {
        // بررسی تعداد نشست‌های فعال
        if ($this->hasTooManySessions($request)) {
            $this->logViolation($request, 'too_many_sessions');

            return response()->json([
                'message' => 'تعداد نشست‌های فعال بیش از حد مجاز است.',
                'error_code' => 'too_many_sessions',
            ], 403);
        }

        // بررسی IP و User Agent
        if ($this->isSessionHijacked($request)) {
            $this->logViolation($request, 'session_hijacking');
            Session::invalidate();

            return response()->json([
                'message' => 'نشست نامعتبر است. لطفا مجددا وارد شوید.',
                'error_code' => 'invalid_session',
            ], 403);
        }

        // تنظیم زمان انقضای نشست
        $this->setSessionLifetime();

        // بازسازی شناسه نشست
        if ($this->shouldRegenerateSession()) {
            Session::regenerate(true);
        }

        return $next($request);
    }

    protected function hasTooManySessions(Request $request): bool
    {
        if (! auth()->check()) {
            return false;
        }

        $userId = auth()->id();
        $currentSessionId = Session::getId();

        // بررسی تعداد نشست‌های فعال در دیتابیس
        $activeSessions = \DB::table('sessions')
            ->where('user_id', $userId)
            ->where('id', '!=', $currentSessionId)
            ->count();

        return $activeSessions >= $this->getMaxSessions();
    }

    protected function isSessionHijacked(Request $request): bool
    {
        if (! Session::has('ip_address') || ! Session::has('user_agent')) {
            return false;
        }

        return Session::get('ip_address') !== $request->ip() ||
               Session::get('user_agent') !== $request->userAgent();
    }

    protected function setSessionLifetime(): void
    {
        config(['session.lifetime' => $this->getSessionLifetime()]);
    }

    protected function shouldRegenerateSession(): bool
    {
        $lastRegeneration = Session::get('last_regeneration');
        if (! $lastRegeneration) {
            return true;
        }

        return now()->diffInMinutes($lastRegeneration) >= $this->getRegenerateInterval();
    }

    protected function logViolation(Request $request, string $type): void
    {
        Log::warning('نقض امنیت نشست', [
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'type' => $type,
            'user_id' => auth()->id(),
        ]);
    }
}
