<?php

namespace App\Classes\Modules\Accounts\ControllersLogic;


use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\SendUserVerificationEmail;
use App\Classes\Modules\Accounts\DataTransferObjects\RegistrationObject;
use App\Classes\Modules\Accounts\Services\CreatesUser;
use App\Classes\Modules\Accounts\Services\GeneratesEmailVerificationAttempt;
use App\Classes\Modules\Accounts\Standards\Rules\CanCreateUser;
use App\Classes\Modules\Companies\DataTransferObjects\ConnectionObject;
use App\Classes\Modules\Companies\DataTransferObjects\EmployeeObject;
use App\Classes\Modules\Companies\DataTransferObjects\ModuleObject;
use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor;
use App\Classes\Modules\Companies\Services\CreatesCompanyConnection;
use App\Classes\Modules\Companies\Services\CreatesCompanyEmployee;
use App\Classes\Modules\Companies\Services\CreatesCompanyModule;
use App\Classes\Modules\Companies\Services\GeneratesUniqueAccountNumber;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\ValueObjects\Constants\CompanyRoles;
use App\Classes\ValueObjects\Constants\ModuleTypes;
use App\Classes\ValueObjects\Constants\Notifications;
use App\Models\Company;
use App\Models\CompanyModule;
use App\Models\User;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class CreateUserLogic extends AbstractControllerLogic
{

    protected function notification():array {
        return Notifications::REGISTRATION;
    }

    /** @var GeneratesUniqueAccountNumber */
    private $generatesUniqueAccountNumber;

    /** @var CanCreateUser */
    private $canCreateUser;

    /** @var CreatesUser */
    private $createsUser;

    /** @var CreateCompanyProcessor */
    private $createCompanyProcessor;

    /** @var CreatesCompanyModule */
    private $createsCompanyModule;

    /** @var CreatesCompanyEmployee */
    private $createsCompanyEmployee;

    /** @var CreatesCompanyConnection */
    private $createsCompanyConnection;

    /** @var CreateContactProcessor */
    private $createContactProcessor;

    /** @var AuthenticateUserLogic */
    private $authenticateUserLogic;

    /** @var GeneratesEmailVerificationAttempt */
    private $generatesEmailVerificationAttempt;

    /** @var SendUserVerificationEmail */
    private $sendUserVerificationEmail;

    /**
     * CreateUserLogic constructor.
     * @param GeneratesUniqueAccountNumber $generatesUniqueAccountNumber
     * @param CanCreateUser $canCreateUser
     * @param CreatesUser $createsUser
     * @param CreateCompanyProcessor $createCompanyProcessor
     * @param CreatesCompanyModule $createsCompanyModule
     * @param CreatesCompanyEmployee $createsCompanyEmployee
     * @param CreatesCompanyConnection $createsCompanyConnection
     * @param CreateContactProcessor $createContactProcessor
     * @param AuthenticateUserLogic $authenticateUserLogic
     * @param GeneratesEmailVerificationAttempt $generatesEmailVerificationAttempt
     * @param SendUserVerificationEmail $sendUserVerificationEmail
     */
    public function __construct(GeneratesUniqueAccountNumber $generatesUniqueAccountNumber, CanCreateUser $canCreateUser, CreatesUser $createsUser, CreateCompanyProcessor $createCompanyProcessor, CreatesCompanyModule $createsCompanyModule, CreatesCompanyEmployee $createsCompanyEmployee, CreatesCompanyConnection $createsCompanyConnection, CreateContactProcessor $createContactProcessor, AuthenticateUserLogic $authenticateUserLogic, GeneratesEmailVerificationAttempt $generatesEmailVerificationAttempt, SendUserVerificationEmail $sendUserVerificationEmail)
    {
        $this->generatesUniqueAccountNumber = $generatesUniqueAccountNumber;
        $this->canCreateUser = $canCreateUser;
        $this->createsUser = $createsUser;
        $this->createCompanyProcessor = $createCompanyProcessor;
        $this->createsCompanyModule = $createsCompanyModule;
        $this->createsCompanyEmployee = $createsCompanyEmployee;
        $this->createsCompanyConnection = $createsCompanyConnection;
        $this->createContactProcessor = $createContactProcessor;
        $this->authenticateUserLogic = $authenticateUserLogic;
        $this->generatesEmailVerificationAttempt = $generatesEmailVerificationAttempt;
        $this->sendUserVerificationEmail = $sendUserVerificationEmail;
    }


    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ErrorException
     */
    public function logic(Request $request): JsonResponse {

        try {

            $registrationObject = new RegistrationObject($request->input('email'), $request->input('name'),
                $request->input('password'), $request->input('confirm_password'));

            $this->canCreateUser->passes($registrationObject);

            /** @var User $user */
            $user = $this->createsUser->execute($registrationObject);

//            $attempt = $this->generatesEmailVerificationAttempt->execute($user);

//            $this->sendUserVerificationEmail::dispatch($user, $attempt);

            $request->request->set('name', $request->input('type') === 1 ? $request->input('company_name') : $request->input('name'));

            /** @var Company $company */
            $company = $this->createCompanyProcessor->execute($request);

            $request->request->add(['company_id' => $company->id, 'name' => $registrationObject->getName()]);
            $this->createContactProcessor->execute($request);

            /** @var CompanyModule $module */
            $module = $this->createsCompanyModule->execute(new ModuleObject($company, ModuleTypes::IMPORTER));

            $this->createsCompanyEmployee->execute(new EmployeeObject($module, $user, CompanyRoles::OWNER));

            $this->createsCompanyConnection->execute(new ConnectionObject($module, CompanyModule::find(1)));

            return $this->authenticateUserLogic->execute($request);

        } catch (\Exception $exception){
            throw new ErrorException($exception->getMessage(), $exception->getCode());
        }
    }

}
