<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\DB;

class VerifySpaCsrf
{
    /**
     * Check session cookie + DB session (when using database driver)
     * and validate XSRF token cookie vs header for SPA requests.
     *
     * Note: Only enforces for "unsafe" HTTP methods.
     */
    public function handle(Request $request, Closure $next)
    {
        // Only enforce for state-changing methods
        if (!in_array(strtoupper($request->method()), ['POST', 'PUT', 'PATCH', 'DELETE'])) {
            return $next($request);
        }

        // Session cookie name (defaults to laravel_session)
        $cookieName = config('session.cookie', 'laravel_session');

        // Get raw cookie value from incoming request
        $rawCookie = $request->cookies->get($cookieName);

        if (empty($rawCookie)) {
            return response()->json(['message' => 'Missing session cookie'], 419);
        }

        // Try to decrypt the cookie (if it is still encrypted).
        // If EncryptCookies already ran, $rawCookie may already be decrypted.
        try {
            $sessionId = app('encrypter')->decrypt($rawCookie);
        } catch (DecryptException $e) {
            // cookie probably already decrypted by EncryptCookies
            $sessionId = $rawCookie;
        } catch (\Throwable $e) {
            return response()->json(['message' => 'Invalid session cookie'], 419);
        }

        // If using database driver, check session exists in sessions table
        if (config('session.driver') === 'database') {
            $table = config('session.table', 'sessions');
            $row = DB::table($table)->where('id', $sessionId)->first();
            if (!$row) {
                return response()->json(['message' => 'Session not found or expired'], 419);
            }
        }

        // CSRF check: cookie vs header (axios normally sets X-XSRF-TOKEN)
        $csrfCookie = $request->cookie('XSRF-TOKEN');
        $csrfHeader = $request->header('X-CSRF-TOKEN') ?: $request->header('X-XSRF-TOKEN');

        if (!$csrfCookie || !$csrfHeader) {
            return response()->json(['message' => 'CSRF token missing'], 419);
        }

        // Cookie is URL-encoded in browsers; decode both sides and compare
        $cookieVal = urldecode($csrfCookie);
        $headerVal = urldecode($csrfHeader);

        /*   if (!hash_equals($cookieVal, $headerVal)) {
               return response()->json(['message' => 'CSRF token mismatch!'], 419);
           }
        */
        // all checks ok
        return $next($request);
    }
}
