<?php

namespace App\Support;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class Impersonation
{
    public const SESSION_IMPERSONATOR_ID = 'impersonator_id';

    public const SESSION_READONLY = 'impersonation_readonly';

    public const SESSION_RETURN_URL = 'impersonation_return_url';

    public static function isActive(Request $request): bool
    {
        return $request->session()->has(self::SESSION_IMPERSONATOR_ID);
    }

    public static function isReadOnly(Request $request): bool
    {
        return filter_var(
            $request->session()->get(self::SESSION_READONLY, false),
            FILTER_VALIDATE_BOOL,
        );
    }

    public static function impersonator(Request $request): ?User
    {
        $id = $request->session()->get(self::SESSION_IMPERSONATOR_ID);

        if ($id === null) {
            return null;
        }

        return User::query()->find($id);
    }

    public static function start(Request $request, User $admin, User $target, bool $readOnly = true): void
    {
        $request->session()->put(self::SESSION_IMPERSONATOR_ID, $admin->id);
        $request->session()->put(self::SESSION_READONLY, $readOnly);
        $request->session()->put(
            self::SESSION_RETURN_URL,
            route('admin.users.edit', $target),
        );

        Auth::login($target);
        $request->session()->regenerate();
    }

    public static function stop(Request $request): ?User
    {
        $impersonatorId = $request->session()->get(self::SESSION_IMPERSONATOR_ID);
        $returnUrl = $request->session()->get(self::SESSION_RETURN_URL);

        $request->session()->forget([
            self::SESSION_IMPERSONATOR_ID,
            self::SESSION_READONLY,
            self::SESSION_RETURN_URL,
        ]);

        if ($impersonatorId === null) {
            return null;
        }

        $admin = User::query()->find($impersonatorId);

        if ($admin === null) {
            Auth::logout();

            return null;
        }

        Auth::login($admin);
        $request->session()->regenerate();
        $request->session()->put('impersonation_stopped_return_url', $returnUrl);

        return $admin;
    }

    public static function consumeStoppedReturnUrl(Request $request): ?string
    {
        $url = $request->session()->pull('impersonation_stopped_return_url');

        return is_string($url) && $url !== '' ? $url : null;
    }
}
