<?php

declare(strict_types=1);

/*
 * This file is part of dacore bundle for Contao.
 *
 * (c) Benjamin Roth
 *
 * @license commercial
 */

namespace vossmedien\DacoreBundle\Controller\Frontend\Module;

use Contao\Controller;
use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController;
use Contao\CoreBundle\ServiceAnnotation\FrontendModule;
use Contao\FormModel;
use Contao\ModuleModel;
use Contao\PageModel;
use Contao\Template;
use Haste\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\FormDataPart;
use vossmedien\DacoreBundle\API\Softgarden;
use vossmedien\DacoreBundle\Generator\CodeGenerator;
use vossmedien\DacoreBundle\Model\VrApiUserCounterModel;

/**
 * @FrontendModule(JobApplicationFormController::TYPE, category="miscellaneous")
 */
class JobApplicationFormController extends AbstractFrontendModuleController
{
    public const TYPE = 'dacore_jobapplication';

    /**
     * @var Softgarden
     */
    protected $api;

    /**
     * @var RequestStack
     */
    protected $requestStack;

    /**
     * @var Form
     */
    protected $Form;

    public function __construct(Softgarden $api, RequestStack $requestStack)
    {
        $this->api = $api;
        $this->requestStack = $requestStack;
    }


    protected function getResponse(Template $template, ModuleModel $model, Request $request): ?Response
    {
        global $objPage;
        $session = $this->requestStack->getSession();
        $arrApiUser = [];
        $jobId = intval($request->get('jobid'));

        if (!$jobId)
        {
            $pageType = $GLOBALS['TL_PTY']['error_404'];
            $objHandler = new $pageType();
            return $objHandler->getResponse($objPage);
        }


        if (!$session->has('vr_api_user'))
        {
            // DEBUG
            /*$arrApiUser = [
                'username' => 'bewerber3@dacore.api',
                'password' => 'Ui:v%qCm<3B]'
            ];
            $session->set('vr_api_user',$arrApiUser);*/



            $time = time();

            $NewApiUser = new VrApiUserCounterModel();
            $NewApiUser->setRow(['tstamp'=>$time,'created'=>$time]);
            $NewApiUser->save()->refresh();

            $arrApiUser = [
                'username' => 'bewerber' . $NewApiUser->id . '@dacore.api',
                'password' => $this->generatePassword()
            ];

            if ($this->api->createApplicantUser($arrApiUser['username'],$arrApiUser['password']))
            {
                $session->set('vr_api_user',$arrApiUser);
                Controller::reload();
            }
        } else {
            $arrApiUser = $session->get('vr_api_user');
        }

        if (($userToken = $this->api->getUserAccessToken($arrApiUser['username'],$arrApiUser['password'])) === null)
        {
            $template->hasError = true;
            $template->errorMsg = 'Aufgrund eines technischen Fehlers ist eine Bewerbung auf diese Stelle derzeit nicht möglich [ERR-1001]';
            return $template->getResponse();
        }

        if ($this->api->hasApplied($jobId,$userToken->token_type,$userToken->access_token))
        {
            $applicationId = $this->api->getApplicationId($jobId,$userToken->token_type,$userToken->access_token);
            if ($this->api->deleteApplication($applicationId,$userToken->token_type,$userToken->access_token))
            {
                $applicationId = $this->api->startApplication($jobId,$userToken->token_type,$userToken->access_token);
            }
        } else {
            $applicationId = $this->api->startApplication($jobId,$userToken->token_type,$userToken->access_token);
        }


        $application = $this->api->getApplication($applicationId,$userToken->token_type,$userToken->access_token);

        if ($application !== null && isset($application->applicationEditable) && !$application->applicationEditable)
        {
            $template->hasError = true;
            $template->errorMsg = 'Sie haben sich bereits auf diese Stelle beworben [ERR-2001]';
            return $template->getResponse();
        }
        elseif ($application === null || !isset($application->applicationId))
        {
            $template->hasError = true;
            $template->errorMsg = 'Aufgrund eines technischen Fehlers ist eine Bewerbung auf diese Stelle derzeit nicht möglich [ERR-1002]';
            return $template->getResponse();
        }

        $strFormId = 'jobapplication-form';

        $this->Form = new Form($strFormId,'POST', function($objHaste) {
            return \Input::post('FORM_SUBMIT') === $objHaste->getFormId();
        });

        $this->Form->addFieldsFromFormGenerator($model->form, function(&$strField, &$arrDca) {
            return true;
        });

        // Form submitted
        if ($this->Form->validate())
        {
            $blnSuccess = false;
            $blnDoNotSubmit = false;
            $applicationProfileDTO = [];

            $this->addValueIfPresent($applicationProfileDTO,'firstname');
            $this->addValueIfPresent($applicationProfileDTO,'lastname');
            $this->addValueIfPresent($applicationProfileDTO,'sex');
            $this->addValueIfPresent($applicationProfileDTO,'email');
            $this->addValueIfPresent($applicationProfileDTO,'phone');
            $this->addValueIfPresent($applicationProfileDTO,'coverLetterText');

            if (!$this->api->addApplicationInfo($applicationProfileDTO, $applicationId, $userToken->token_type,$userToken->access_token))
            {
                $blnDoNotSubmit = true;
            }

            if ($this->Form->hasUploads()) {
                if (isset($_SESSION['FILES']['cv']))
                {
                    if (!$this->api->addApplicationFileCV($_SESSION['FILES']['cv']['tmp_name'], $_SESSION['FILES']['cv']['name'], $_SESSION['FILES']['cv']['type'],$applicationId,$userToken->token_type,$userToken->access_token))
                    {
                        $blnDoNotSubmit = true;
                    }
                }

                if (isset($_SESSION['FILES']['coverLetterFile']))
                {
                    if (!$this->api->addApplicationFile($_SESSION['FILES']['coverLetterFile']['tmp_name'], $_SESSION['FILES']['coverLetterFile']['name'], $_SESSION['FILES']['coverLetterFile']['type'],$applicationId,$userToken->token_type,$userToken->access_token))
                    {
                        $blnDoNotSubmit = true;
                    }
                }

                for ($i = 1; $i < 4; $i++)
                {
                    $fieldname = 'attachment_' . $i;

                    if (isset($_SESSION['FILES'][$fieldname]))
                    {
                        if (!$this->api->addApplicationFile($_SESSION['FILES'][$fieldname]['tmp_name'], $_SESSION['FILES'][$fieldname]['name'], $_SESSION['FILES'][$fieldname]['type'],$applicationId,$userToken->token_type,$userToken->access_token))
                        {
                            $blnDoNotSubmit = true;
                        }
                    }
                }
            }

            if (!$blnDoNotSubmit)
            {
                // Finalize Application
                $blnSuccess = $this->api->finalizeApplication($applicationId,$userToken->token_type,$userToken->access_token);
                if ($blnSuccess && ($FormModel = FormModel::findByPk($model->form)) !== null && $FormModel->jumpTo && ($successPage = PageModel::findByPk($FormModel->jumpTo)) !== null)
                {
                    Controller::redirect($successPage->getFrontendUrl());
                }

                if ($blnSuccess) {
                    $template->applicationSubmitted = true;
                }
            }

            if (!$blnDoNotSubmit || !$blnSuccess)
            {
                $template->hasError = true;
                $template->errorMsg = 'Ihre Bewerbung konnte aufgrund eines Fehlers nicht übermittelt werden. Bitte versuchen Sie es erneut oder setzen Sie sich mit uns in Verbindung.';
            }
        }

        $template->form = $this->Form->generate();

        return $template->getResponse();
    }

    protected function generatePassword()
    {
        $digits    = array_flip(range('0', '9'));
        $lowercase = array_flip(range('a', 'z'));
        $uppercase = array_flip(range('A', 'Z'));
        $special   = array_flip(str_split('!@#$%^&*()_+=-}{[}]\|;:<>?/'));
        $combined  = array_merge($digits, $lowercase, $uppercase, $special);

        $password  = str_shuffle(array_rand($digits) .
            array_rand($lowercase) .
            array_rand($uppercase) .
            array_rand($special) .
            implode(array_rand($combined, 8)));

        return $password;
    }

    protected function addValueIfPresent(array &$data, string $fieldname)
    {
        if (!$this->Form->isSubmitted() || !$this->Form->hasFormField($fieldname))
        {
            return false;
        }

        if (($value = $this->Form->fetch($fieldname)) !== null)
        {
            $data[$fieldname] = $value;
            return true;
        }

        return false;
    }

}