<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config; // Import Config facade
use Illuminate\Support\Facades\Session;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class CheckProfileInactivity
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
public function handle(Request $request, Closure $next)
{
    // Only proceed if a user is authenticated
    if (!Auth::check()) {
        Session::forget('last_activity'); // Clear timestamp if user logs out
        return $next($request); // Pass the request to the next middleware - route-level auth middleware will handle redirect
    }

    // When user is authenticated
    $activeProfileType = Session::get('activeProfileType', \App\Models\User::class); // Default to User class if not set

    // Initialize active profile if not set (happens after login)
    if (!Session::has('activeProfileId')) {
        $user = Auth::guard('web')->user();
        if ($user) {
            Session::put([
                'activeProfileType'  => \App\Models\User::class,
                'activeProfileId'    => $user->id,
                'activeProfileName'  => $user->name,
                'activeProfilePhoto' => $user->profile_photo_path,
            ]);
        }
    }

    $lastActivity = Session::get('last_activity');

    // If last_activity is not set, initialize it and continue (first request after login)
    if (!$lastActivity) {
        Session::put('last_activity', now());
        return $next($request);
    }

    // Check base session timeout first (this should never exceed SESSION_LIFETIME)
    // This prevents profile-specific timeouts from keeping sessions alive beyond the base session lifetime
    $baseSessionLifetime = Config::get('session.lifetime', 120); // minutes
    $minutesSinceActivity = now()->diffInMinutes($lastActivity);

    // If base session has expired, force logout regardless of profile type
    if ($minutesSinceActivity >= $baseSessionLifetime) {
        $user = Auth::guard('web')->user();
        Auth::guard('web')->logout();
        Session::invalidate();
        Session::regenerateToken();

        // For AJAX requests, return a JSON response indicating logout
        if ($request->expectsJson() || $request->ajax()) {
            return response()->json([
                'message' => __('Your session timed out due to inactivity. Please log in again.'),
                'action' => 'logout',
                'redirect_url' => LaravelLocalization::localizeUrl('/login')
            ], 419); // 419 Authentication Timeout
        } else {
            // For standard browser requests, redirect to login
            $loginUrl = LaravelLocalization::localizeUrl('/login');
            return redirect()->to($loginUrl)
                        ->with('warning', __('Your session timed out due to inactivity. Please log in again.'));
        }
    }

    // Get the specific timeout for the current profile type, or use the default of 120 min.
    $configuredTimeout = timebank_config('profile_timeouts.' . $activeProfileType, timebank_config('profile_timeout_default', 120));

    // Profile-specific timeout cannot exceed base session lifetime
    // This ensures elevated profiles timeout at or before the base session expiration
    $timeoutMinutes = min($configuredTimeout, $baseSessionLifetime);

    // Log when timeout is being capped for debugging purposes
    if ($configuredTimeout > $baseSessionLifetime) {
        \Log::info('Profile timeout capped by SESSION_LIFETIME', [
            'profile_type' => class_basename($activeProfileType),
            'configured_timeout' => $configuredTimeout,
            'session_lifetime' => $baseSessionLifetime,
            'effective_timeout' => $timeoutMinutes,
        ]);
    }

    // Check if the timestamp exists and if the inactivity period has passed
    if ($minutesSinceActivity >= $timeoutMinutes) {
        $user = Auth::guard('web')->user();

        // Check if the current active profile is already the User profile
        if ($activeProfileType === \App\Models\User::class) {
            // If the active profile is User and their session expires, log them out
            Auth::guard('web')->logout();
            Session::invalidate();
            Session::regenerateToken();

            // For AJAX requests, return a JSON response indicating logout
            if ($request->expectsJson() || $request->ajax()) {
                return response()->json([
                    'message' => __('Your session timed out due to inactivity. Please log in again.'),
                    'action' => 'logout', // Indicate a full logout
                    'redirect_url' => LaravelLocalization::localizeUrl('/login') // Provide login URL
                ], 419); // 419 Authentication Timeout
            } else {
                // For standard browser requests, redirect to login
                $loginUrl = LaravelLocalization::localizeUrl('/login');
                return redirect()->to($loginUrl)
                            ->with('warning', __('Your session timed out due to inactivity. Please log in again.'));
            }
        } else {
            // If the active profile is an elevated profile (Bank, Admin, etc.), switch back to User profile
            Session::put([
                'activeProfileType'  => \App\Models\User::class,
                'activeProfileId'    => $user->id,
                'activeProfileName'  => $user->name,
                'activeProfilePhoto' => $user->profile_photo_path,
                'profile-switched-notification' => true,
            ]);

            session(['notification.alert' => 'Your previous profile session timed out due to inactivity.']); // Will become a translation key in notification component

            Session::forget('last_activity'); // Clear the timestamp

            event(new \App\Events\ProfileSwitchEvent($user));

            // Check if the request expects JSON (common for AJAX) or is an AJAX request
            if ($request->expectsJson() || $request->ajax()) {
                session(['notification.alert' => 'Your previous profile session timed out due to inactivity.']); // Will become a translation key in notification component

                // Get the user's locale from the session (set by localization middleware)
                $userLocale = Session::get('locale', config('app.fallback_locale'));
                // Use LaravelLocalization to get the full, localized URL
                $redirectUrl = LaravelLocalization::getURLFromRouteNameTranslated($userLocale, 'routes.main');
                Session::save(); 

                // Return a JSON response indicating timeout, use 419 status code
                return response()->json([
                    'message' => __('Your previous profile session timed out due to inactivity.'),
                    'action' => 'redirect', // Change action name to 'redirect'
                    'redirect_url' => $redirectUrl // <-- Add URL to payload
                ], 419); // 419 Authentication Timeout
            } else {
                // For standard browser requests, perform the redirect with flash message
                $mainUrl = LaravelLocalization::localizeUrl('/main-page');
                return redirect()->to($mainUrl)
                            ->with('warning', __('Your previous profile session timed out due to inactivity.'));
            }
        }
    }

    // Update the activity timestamp on relevant requests
    // Exclude background heartbeats but allow user-initiated Livewire interactions
    $isLivewireUpdate = $request->is(['*/livewire/update', 'livewire/update']);
    $isUserInteraction = $isLivewireUpdate && $request->has('components');

    if (!$request->is(['api/messenger/heartbeat']) && (!$isLivewireUpdate || $isUserInteraction)) {
        Session::put('last_activity', now());
    }

    return $next($request); // Ensure the request is passed to the next middleware
}

}

