<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Symfony\Component\HttpFoundation\Response;

/**
 * App sessions are subordinate to the platform (auth.ladill.com) session.
 * When the platform session ends, clear this app's local session too.
 *
 * Re-checks auth.ladill.com at most once per TTL — not on every request.
 * Client-side sso-keepalive still pings periodically between checks.
 */
class EnsurePlatformSession
{
    private const VERIFY_TTL_SECONDS = 90;

    public function handle(Request $request, Closure $next): Response
    {
        if (! Auth::check()) {
            return $next($request);
        }

        $authDomain = trim((string) config('app.auth_domain', ''));
        if ($authDomain === '') {
            return $next($request);
        }

        $verifiedAt = (int) $request->session()->get('platform_session_verified_at', 0);
        if ($verifiedAt > 0 && (time() - $verifiedAt) < self::VERIFY_TTL_SECONDS) {
            return $next($request);
        }

        try {
            $cookieHeader = (string) $request->headers->get('Cookie', '');
            if ($cookieHeader === '') {
                return $this->deferPlatformCheck($request, $next);
            }

            $response = Http::withHeaders(['Cookie' => $cookieHeader])
                ->timeout(3)
                ->connectTimeout(2)
                ->get('https://'.$authDomain.'/sso/ping');
        } catch (\Throwable) {
            return $next($request);
        }

        if ($response->status() === 401) {
            // Server-side ping forwards cookies from this app's host only. Platform
            // session cookies on auth.ladill.com are often absent, which yields a
            // false 401 and an infinite /sso/connect loop if we sign the user out.
            // Client keepalive (sso-keepalive partial) performs the real check.
            return $this->deferPlatformCheck($request, $next);
        }

        if ($response->successful()) {
            $request->session()->put('platform_session_verified_at', time());
        }

        return $next($request);
    }

    private function deferPlatformCheck(Request $request, Closure $next): Response
    {
        $request->session()->put('platform_session_verified_at', time());

        return $next($request);
    }

    private function clearAppSession(Request $request): Response
    {
        Auth::logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return redirect()->route('sso.connect', [
            'redirect' => $request->fullUrl(),
            'interactive' => 1,
        ]);
    }
}
