<?php

namespace App\Http\Controllers\Api\Auth;

use App\Http\Controllers\Controller;
use App\Services\ApplicationUrlService;
use App\Support\SessionTimeoutConfig;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

/**
 * Session idle timeout checks (web session cookie).
 */
class SessionTimeoutController extends Controller
{
    /** Shared session key for last-activity tracking. */
    private const SESSION_KEY = 'last_activity';

    public function __construct(
        private ApplicationUrlService $urls,
    ) {
    }

    /**
     * Returns timeout metadata for the web portal.
     */
    public function getTimeoutConfig(): JsonResponse
    {
        return response()->json([
            'success' => true,
            'timeout' => SessionTimeoutConfig::TIMEOUT_DURATION,
            'warning_time' => SessionTimeoutConfig::WARNING_THRESHOLD,
            'check_interval' => SessionTimeoutConfig::CHECK_INTERVAL,
            'logout_url' => $this->urls->webLogoutUrl(),
            'keep_alive_url' => $this->urls->webSessionPingUrl(),
            'check_url' => $this->urls->webSessionCheckTimeoutUrl(),
        ]);
    }

    public function checkTimeout(Request $request): JsonResponse
    {
        $session = $request->session();

        if (! $session->has(self::SESSION_KEY)) {
            return $this->expireSession($request);
        }

        $lastActivity = (int) $session->get(self::SESSION_KEY);
        $elapsed = time() - $lastActivity;

        if ($elapsed > SessionTimeoutConfig::TIMEOUT_DURATION) {
            return $this->expireSession($request);
        }

        if ($elapsed > SessionTimeoutConfig::WARNING_THRESHOLD) {
            return response()->json([
                'status' => 'warning',
                'time_remaining' => SessionTimeoutConfig::TIMEOUT_DURATION - $elapsed,
            ]);
        }

        return response()->json([
            'status' => 'active',
            'time_remaining' => SessionTimeoutConfig::TIMEOUT_DURATION - $elapsed,
        ]);
    }

    public function pingActivity(Request $request): JsonResponse
    {
        $session = $request->session();

        if (! $session->has(self::SESSION_KEY)
            || (time() - (int) $session->get(self::SESSION_KEY)) > SessionTimeoutConfig::TIMEOUT_DURATION) {
            return $this->expireSession($request);
        }

        $session->put(self::SESSION_KEY, time());

        return response()->json([
            'status' => 'active',
            'time_remaining' => SessionTimeoutConfig::TIMEOUT_DURATION,
        ]);
    }

    private function expireSession(Request $request): JsonResponse
    {
        $request->session()->flash('error', 'Your session has expired due to inactivity.');
        $request->session()->forget(self::SESSION_KEY);

        Auth::guard('web')->logout();

        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return response()->json([
            'status' => 'expired',
            'redirect' => $this->urls->webLoginUrl(),
            'message' => 'Your session has expired due to inactivity.',
        ]);
    }
}
