<?php

namespace App\Livewire\Settings;

use App\Services\SessionService;
use App\Support\Confirm\ConfirmToken;
use App\Support\Confirm\InvalidConfirmToken;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\On;
use Livewire\Component;

class Sessions extends Component
{
    /**
     * Open the R5 confirm for "sign out other devices". The current session is
     * kept; only the other rows are deleted on confirm. The modal writes the
     * audit row (session.logout_others) and re-dispatches the apply event.
     */
    public function confirmLogoutOthers(): void
    {
        $this->dispatch('openModal',
            component: 'modals.confirm-action',
            arguments: [
                'heading' => __('sessions.logout_others'),
                'body' => __('sessions.logout_others_body'),
                'confirmLabel' => __('sessions.logout_others'),
                'danger' => true,
                'icon' => 'logout',
                'notify' => __('sessions.logout_others_notify'),
                'token' => ConfirmToken::issue(
                    'sessionsLogoutOthers',
                    [],
                    'session.logout_others',
                    Auth::user()?->email,
                ),
            ],
        );
    }

    #[On('sessionsLogoutOthers')]
    public function logoutOthers(string $confirmToken, SessionService $sessions): void
    {
        try {
            ConfirmToken::consume($confirmToken, 'sessionsLogoutOthers');
        } catch (InvalidConfirmToken) {
            return; // forged / replayed / direct-bypass attempt — no-op
        }

        $sessions->logoutOtherDevices(Auth::user());
        // List re-renders on the next round trip; no explicit refresh needed.
    }

    /**
     * Open the R5 confirm for the destructive GLOBAL logout. On confirm every
     * session is wiped and every remember_token rotated — including this
     * operator's, so the apply handler redirects to login.
     */
    public function confirmLogoutAll(): void
    {
        abort_unless(auth()->user()?->can('manage-users'), 403);
        $this->dispatch('openModal',
            component: 'modals.confirm-action',
            arguments: [
                'heading' => __('sessions.logout_all'),
                'body' => __('sessions.logout_all_body'),
                'confirmLabel' => __('sessions.logout_all'),
                'danger' => true,
                'icon' => 'power',
                // Defer the toast: this session is about to be destroyed and the
                // user redirected to login, so a toast would never be seen.
                'notify' => '',
                'token' => ConfirmToken::issue(
                    'sessionsLogoutAll',
                    [],
                    'session.logout_all',
                    Auth::user()?->email,
                ),
            ],
        );
    }

    #[On('sessionsLogoutAll')]
    public function logoutAll(string $confirmToken, SessionService $sessions)
    {
        abort_unless(auth()->user()?->can('manage-users'), 403);
        try {
            ConfirmToken::consume($confirmToken, 'sessionsLogoutAll');
        } catch (InvalidConfirmToken) {
            return; // forged / replayed / direct-bypass attempt — no-op
        }

        // Truncates all sessions + rotates every remember_token. This logs the
        // operator out too, so push them to login (AuthenticateSession would
        // otherwise bounce the very next request).
        $sessions->logoutEveryone();
        Auth::logout();

        return $this->redirect(route('login'), navigate: true);
    }

    public function render()
    {
        return view('livewire.settings.sessions', [
            'sessions' => app(SessionService::class)->forUser(Auth::user()),
        ]);
    }
}
