<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Services\AuditLog;
use App\Services\CurrentContext;
use App\Services\UserLanding;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;

/**
 * Tenant-side handler for landlord impersonation. Consumes the single-use token
 * minted by the central panel and establishes a `web` session as the target user
 * — but only when the token's tenant matches the subdomain we're on, so a token
 * can never be replayed against a different tenant.
 */
class ImpersonationController extends Controller
{
    public function consume(Request $request, CurrentContext $context): RedirectResponse
    {
        // Resolved explicitly from the route: under path tenancy the route's
        // {workspace} prefix parameter is also in play, and the constructor's
        // implicit positional binding was handing the middleware-earlier
        // parameter ({workspace}) to `string $token` — a hard-to-spot 403 for
        // every hand-off link (docs/path-based-tenancy-plan.md Phase 4).
        $token = (string) $request->route('token');

        $data = Cache::pull("impersonate:{$token}");

        if (! $data || (int) $data['tenant_id'] !== (int) $context->tenantId()) {
            abort(403, 'This impersonation link is invalid or has expired.');
        }

        $user = User::query()->find($data['user_id']);
        if (! $user) {
            abort(404);
        }

        Auth::guard('web')->login($user);
        $request->session()->regenerate();
        $request->session()->put('impersonator', ['by_email' => $data['by_email'] ?? 'platform admin']);

        AuditLog::record('user.impersonated', $user, ['central_admin' => $data['by_email'] ?? null], $user->id);

        return redirect()->to(UserLanding::urlFor($user))
            ->with('warning', "You are now impersonating {$user->name}.");
    }

    public function stop(Request $request): RedirectResponse
    {
        $request->session()->forget('impersonator');
        Auth::guard('web')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return redirect()->route('filament.app.auth.login')->with('success', 'Impersonation ended.');
    }
}
