<?php

namespace App\Classes\Modules\ControllersLogic\Accounts;


use App\Classes\Modules\Accounts\DataTransferObjects\UserInvitationObject;
use App\Classes\Modules\Accounts\DataTransferObjects\UserObject;
use App\Classes\Modules\Accounts\Exceptions\CannotCreateOrderException;
use App\Classes\Modules\Accounts\Services\CreatesUserAccount;
use App\Classes\Modules\ControllerLogic\Exceptions\InternalServerErrorException;
use App\Classes\Modules\ControllerLogic\Exceptions\MalformedRequestException;
use App\Models\UserInvitation;
use App\Traits\DeterminesIfUserPasswordMatchesRequirements;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class RegisterAccountLogic
{

    use DeterminesIfUserPasswordMatchesRequirements;

    /** @var CreatesUserAccount */
    private $createsUserAccount;

    /**
     * RegisterAccountLogic constructor.
     *
     * @param CreatesUserAccount $createsUserAccount
     */
    public function __construct(
        CreatesUserAccount $createsUserAccount
    ) {
        $this->createsUserAccount = $createsUserAccount;
    }

    /**
     * @param Request $request
     * @return JsonResponse
     * @throws InternalServerErrorException
     * @throws MalformedRequestException
     */
    public function execute(Request $request) {

        // throws malformed request exception if the password is invalid
        if ($this->checkPasswordAndThrowIfInvalid($request->get('password')) === false) {
            throw new MalformedRequestException('Password strength is insufficient');
        }

        $invitation = UserInvitation::where('email', $request->input('email'))
            ->where('hash', $request->input('hash'))
            ->where('is_complete', false)->first();

        if(!$invitation){
            throw new MalformedRequestException('invitation hash is invalid');
        }

        $invite = new UserInvitationObject($invitation->role_id, $invitation->email, $invitation->hash);

        try {

            // the email doesn't exist in the database, so create the user
            $object = new UserObject($request->get('first_name'), $request->get('last_name'),
                $invite->getInviteeEmail(), $request->get('password'), $invite->getRole(), true);


            $user = $this->createsUserAccount->execute($object);

            UserInvitation::where('email', $invite->getInviteeEmail())
                ->where('hash', $invite->getHash())->update(['is_complete' => true]);

            auth()->loginUsingId($user->id);

            return redirect()->route('dashboard');

        } catch (CannotCreateOrderException $exception) {
            throw new InternalServerErrorException("Failed to create user because {$exception->getMessage()}");
        }
    }
}