<?php

namespace Botble\ACL\Services;

use Botble\ACL\Models\User;
use Botble\Base\Facades\BaseHelper;
use Botble\Support\Services\ProduceServiceInterface;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Throwable;

class ChangePasswordService implements ProduceServiceInterface
{
    public function execute(Request $request): bool|User
    {
        $currentUser = $request->user();

        if (! $currentUser->isSuperUser()) {
            if (! Hash::check($request->input('old_password'), $currentUser->getAuthPassword())) {
                throw new Exception(trans('core/acl::users.current_password_not_valid'));
            }
        }

        if (($userId = $request->input('id')) && $userId === $currentUser->getKey()) {
            $user = $currentUser;
        } else {
            $user = User::query()->findOrFail($userId);
        }

        $password = $request->input('password');

        $user->password = Hash::make($password);
        $user->sessions_invalidated_at = Carbon::now();
        $user->setRememberToken(Str::random(60));
        $user->save();

        /**
         * @var User $user
         */
        if ($user->getKey() != $currentUser->getKey()) {
            try {
                Auth::setUser($user);
                Auth::logoutOtherDevices($password);
            } catch (Throwable $exception) {
                BaseHelper::logError($exception);
            }
        }

        do_action(USER_ACTION_AFTER_UPDATE_PASSWORD, USER_MODULE_SCREEN_NAME, $request, $user);

        return $user;
    }
}
