<?php

namespace Trainingssystem\Module\Limesurvey;

use Trainingssystem\Module\Limesurvey\Api\LimesurveyApi;
use Trainingssystem\Module\Limesurvey\Api\Request\GetSurveysRequest;
use Trainingssystem\Module\Limesurvey\Api\Request\AddParticipantRequest;
use Trainingssystem\Module\Limesurvey\Api\Request\SetParticipantPropertiesRequest;
use Trainingssystem\Module\Limesurvey\Api\Request\GetParticipantPropertiesRequest;
use Trainingssystem\Module\Limesurvey\Api\Model\Participant;
use Trainingssystem\Module\Limesurvey\Api\Model\Token;

define('LIMESURVEY_ID_BEFORE_TRAINING', 'limesurvey_id_before_training');
define('LIMESURVEY_ID_AFTER_TRAINING', 'limesurvey_id_after_training');
define('LIMESURVEY_ID_AFTER_TRAINING_CHECK', 'limesurvey_id_after_training_check');
define('DAYS_TILL_SECOND_SURVEY_DEFAULT', 42);
define('DAYS_TILL_SECOND_SURVEY_REMINDER_DEFAULT', 3);
define('DAYS_TILL_THIRD_SURVEY_DEFAULT', 182);
define('DAYS_TILL_THIRD_SURVEY_REMINDER_DEFAULT', 3);

class LimesurveyModule
{
    private $pluginOptions;
    private $surveys;

    public function __construct()
    {
        $this->pluginOptions = get_option(TRAININGSSYSTEM_PLUGIN_SETTINGS, []);

        add_action('limesurvey_cron_hook', [$this, 'limesurveyCronExec']);
        if (!wp_next_scheduled( 'limesurvey_cron_hook')) {
            wp_schedule_event(time(), 'daily', 'limesurvey_cron_hook');
        }
    }

    private function checkSettings () {
        if (!empty($this->pluginOptions['limesurvey_rpc_url'])
            && !empty($this->pluginOptions['limesurvey_rpc_username'])
            && !empty($this->pluginOptions['limesurvey_rpc_password'])) {
            return true;
        }
        return false;
    }

    private function loadSurveys () {
        if ($this->checkSettings()) {
            $api = LimesurveyApi::create();
            $request = new GetSurveysRequest();
            $api->request($request);
            $this->surveys = $request->getSurveys();
        }
    }

    function limesurvey_user($trainingsID, $userId) {
        $this->checkAndRegisterUser(LIMESURVEY_ID_BEFORE_TRAINING, $trainingsID, $userId);
        $this->checkAndRegisterUser(LIMESURVEY_ID_AFTER_TRAINING, $trainingsID, $userId);
        $this->checkAndRegisterUser(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $trainingsID, $userId);
        return true;
    }

    private function checkAndRegisterUser($fieldId, $trainingsID, $userId) {
        if ($this->existsSurvey($fieldId, $trainingsID)) {
            $limesurveyId = $this->getSurveyId($fieldId, $trainingsID);
            if (!$this->getUserSurveyToken($limesurveyId, $userId)) {
                $userData = get_userdata($userId);
                try {
                    $api = LimesurveyApi::create();
                    $participant = new Participant();
                    $participant->setFirstname($userId);
                    $participant->setLastname($userId);
                    $participant->setEmail($userId.'@getcalm-moveon.de');
                    $request = new AddParticipantRequest($limesurveyId, $participant);
                    $api->request($request);

                    $participantsData = $request->getParticipants();
                    if (is_array($participantsData)) {
                        foreach ($participantsData as $index => $participantData) {
                            $token = new Token();
                            $token->setToken(substr(sha1($participantData->getToken()), 0, 15));
                            $tokenRequest = new SetParticipantPropertiesRequest($limesurveyId, $participantData->getTid(), $token);
                            $api->request($tokenRequest);
                            $this->setUserSurveyTid($limesurveyId, $userId, $tokenRequest->getParticipant()->getTid());
                            $this->setUserSurveyToken($limesurveyId, $userId, $tokenRequest->getParticipant()->getToken());
                        }
                    }
                } catch (\Exception $e) {
                    error_log($e->getMessage() . ' | ' . $limesurveyId . ' | ' . $userId);
                }
            }
        }
    }

    function get_limesurvey_status ($trainingsID, $userId) {
        return [
            LIMESURVEY_ID_BEFORE_TRAINING => $this->checkSurvey(LIMESURVEY_ID_BEFORE_TRAINING, $trainingsID, $userId),
            LIMESURVEY_ID_BEFORE_TRAINING.'_id' => $this->existsSurvey(LIMESURVEY_ID_BEFORE_TRAINING, $trainingsID),
            LIMESURVEY_ID_BEFORE_TRAINING.'_enabled' => $this->enableSurvey(LIMESURVEY_ID_BEFORE_TRAINING, $trainingsID, $userId),
            LIMESURVEY_ID_BEFORE_TRAINING.'_url' => $this->surveyUrl(LIMESURVEY_ID_BEFORE_TRAINING, $trainingsID, $userId),
            LIMESURVEY_ID_BEFORE_TRAINING.'_title' => $this->surveyTitle(LIMESURVEY_ID_BEFORE_TRAINING, $trainingsID),

            LIMESURVEY_ID_AFTER_TRAINING => $this->checkSurvey(LIMESURVEY_ID_AFTER_TRAINING, $trainingsID, $userId),
            LIMESURVEY_ID_AFTER_TRAINING.'_id' => $this->existsSurvey(LIMESURVEY_ID_AFTER_TRAINING, $trainingsID),
            LIMESURVEY_ID_AFTER_TRAINING.'_enabled' => $this->enableSurvey(LIMESURVEY_ID_AFTER_TRAINING, $trainingsID, $userId),
            LIMESURVEY_ID_AFTER_TRAINING.'_url' => $this->surveyUrl(LIMESURVEY_ID_AFTER_TRAINING, $trainingsID, $userId),
            LIMESURVEY_ID_AFTER_TRAINING.'_title' => $this->surveyTitle(LIMESURVEY_ID_AFTER_TRAINING, $trainingsID),

            LIMESURVEY_ID_AFTER_TRAINING_CHECK => $this->checkSurvey(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $trainingsID, $userId),
            LIMESURVEY_ID_AFTER_TRAINING_CHECK.'_id' => $this->existsSurvey(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $trainingsID),
            LIMESURVEY_ID_AFTER_TRAINING_CHECK.'_enabled' => $this->enableSurvey(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $trainingsID, $userId),
            LIMESURVEY_ID_AFTER_TRAINING_CHECK.'_url' => $this->surveyUrl(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $trainingsID, $userId),
            LIMESURVEY_ID_AFTER_TRAINING_CHECK.'_title' => $this->surveyTitle(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $trainingsID),
        ];
    }

    private function existsSurvey ($fieldId, $trainingsID) {
        if (!$this->surveys) {
            $this->loadSurveys();
        }

        if (isset($this->surveys)) {
            foreach ($this->surveys as $survey) {
                if ($survey->sid == $this->getSurveyId($fieldId, $trainingsID)) {
                    return true;
                }
            }
        }
        return false;
    }

    private function checkSurvey ($fieldId, $trainingsID, $userId) {
        if ($this->existsSurvey($fieldId, $trainingsID)) {
            $limesurveyId = $this->getSurveyId($fieldId, $trainingsID);
            //Check completed status on the fly to enable restting in Limesurvey.
            //if (!$this->hasCompletedSurvey($limesurveyId, $userId)) {
                try {
                    $api = LimesurveyApi::create();
                    $request = new GetParticipantPropertiesRequest($limesurveyId, $this->getUserSurveyTid($limesurveyId, $userId));
                    $api->request($request);
                    if ($request->getParticipant()->getCompleted() != 'N') {
                        if (!$this->hasCompletedSurvey($limesurveyId, $userId)) {
                            $this->setCompletedSurvey($limesurveyId, $userId);
                        }
                        return true;
                    } else {
                        if ($this->hasCompletedSurvey($limesurveyId, $userId)) {
                            $this->unsetCompletedSurvey($limesurveyId, $userId);
                        }
                        return false;
                    }
                } catch (\Exception $e) {
                    error_log($e->getMessage() . ' | ' . $limesurveyId . ' | ' . $userId);
                }
                return false;
            //} else {
            //    return true;
            //}
        }
        return false;
    }

    private function enableSurvey ($fieldId, $trainingsID, $userId) {
        $userData = get_userdata($userId);
        $userRegister = new \DateTime($userData->user_registered);
        $userRegister->setTime('00', '00', '00');
        $today = new \DateTime();
        $today->setTime('00', '00', '00');
        $daysDiff = $userRegister->diff($today)->days;

        $daysTillSecondSurvey = DAYS_TILL_SECOND_SURVEY_DEFAULT;
        if (isset($this->pluginOptions['limesurvey_days_till_second_survey_email']) && $this->pluginOptions['limesurvey_days_till_second_survey_email'] != '') {
            $daysTillSecondSurvey = $this->pluginOptions['limesurvey_days_till_second_survey_email'];
        }
        $daysTillThirdSurvey = DAYS_TILL_THIRD_SURVEY_DEFAULT;
        if (isset($this->pluginOptions['limesurvey_days_till_third_survey_email']) && $this->pluginOptions['limesurvey_days_till_third_survey_email'] != '') {
            $daysTillThirdSurvey = $this->pluginOptions['limesurvey_days_till_third_survey_email'];
        }

        if ($fieldId == LIMESURVEY_ID_BEFORE_TRAINING) {
            if ($this->hasCompletedSurvey($this->getSurveyId(LIMESURVEY_ID_BEFORE_TRAINING, $trainingsID), $userId)) {
                return false;
            }
            return true;
        } else if ($fieldId == LIMESURVEY_ID_AFTER_TRAINING && $daysDiff >= $daysTillSecondSurvey) {
            if ($this->trainigCompleted($trainingsID, $userId)) {
                return true;
            }
        }  else if ($fieldId == LIMESURVEY_ID_AFTER_TRAINING_CHECK && $daysDiff >= $daysTillThirdSurvey) {
            if ($this->trainigCompleted($trainingsID, $userId)) {
                return true;
            }
        }
        return false;
    }

    private function surveyUrl ($fieldId, $trainingsID, $userId) {
        if ($this->checkSettings()) {
            $limesurveyId = $this->getSurveyId($fieldId, $trainingsID);
            $url = $this->pluginOptions['limesurvey_rpc_url'] ?? '';
            $url = strtok($url, '?');
            $url .= '?r=survey/index&sid=' . $limesurveyId . '&token=' . $this->getUserSurveyToken($limesurveyId, $userId) . '&newtest=Y';
            return $url;
        }
        return false;
    }

    private function surveyTitle ($fieldId, $trainingsID) {
        if (!$this->surveys) {
            $this->loadSurveys();
        }

        if (isset($this->surveys)) {
            foreach ($this->surveys as $survey) {
                if ($survey->sid == $this->getSurveyId($fieldId, $trainingsID)) {
                    return $survey->surveyls_title;
                }
            }
        }
        return '';
    }

    private function trainigCompleted ($trainingsID, $userId) {
        $training = \Trainingssystem_Plugin_Database::getInstance()->TrainingDao->getTrainingByUser($trainingsID, $userId);
        return $training->getFin() == 100;
    }

    private function getSurveyId ($fieldId, $trainingsID) {
        if (function_exists('get_field')) {
            return get_field($fieldId, $trainingsID);
        }
        return 0;
    }

    private function getUserSurveyTid ($limesurveyId, $userId) {
        return get_user_meta($userId, 'limesuvey_tid_'.$limesurveyId, true);
    }

    private function setUserSurveyTid ($limesurveyId, $userId, $tid) {
        add_user_meta($userId, 'limesuvey_tid_' . $limesurveyId, $tid);
    }

    private function getUserSurveyToken ($limesurveyId, $userId) {
        return get_user_meta($userId, 'limesuvey_token_'.$limesurveyId, true);
    }

    private function setUserSurveyToken ($limesurveyId, $userId, $token) {
        add_user_meta($userId, 'limesuvey_token_' . $limesurveyId, $token);
    }

    private function hasCompletedSurvey ($limesurveyId, $userId) {
        return get_user_meta($userId, 'limesuvey_completed_'.$limesurveyId, true);
    }

    private function setCompletedSurvey ($limesurveyId, $userId) {
        add_user_meta($userId, 'limesuvey_completed_' . $limesurveyId, true);
    }

    private function unsetCompletedSurvey ($limesurveyId, $userId) {
        delete_user_meta($userId, 'limesuvey_completed_' . $limesurveyId);
    }

    /*
    function limesurvey_login($user_login, $user) {
        return true;
    }
    */

    public function limesurveyCronExec() {
        if ($this->checkSettings()) {
            $users = get_users([
                'role' => 'subscriber',
                'orderby' => 'ID',
                'order' => 'ASC',
            ]);

            foreach ($users as $user) {
                $userRegister = new \DateTime($user->user_registered);
                $userRegister->setTime('00', '00', '00');
                $today = new \DateTime();
                $today->setTime('00', '00', '00');
                $daysDiff = $userRegister->diff($today)->days;

                $trainings = \Trainingssystem_Plugin_Database::getInstance()->NutzerDao->getTrainings($user->ID);
                foreach ($trainings as $training) {
                    if ($this->existsSurvey(LIMESURVEY_ID_AFTER_TRAINING, $training->getId()) || $this->existsSurvey(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $training->getId())) {
                        $daysTillSecondSurvey = DAYS_TILL_SECOND_SURVEY_DEFAULT;
                        if (isset($this->pluginOptions['limesurvey_days_till_second_survey_email']) && $this->pluginOptions['limesurvey_days_till_second_survey_email'] != '') {
                            $daysTillSecondSurvey = $this->pluginOptions['limesurvey_days_till_second_survey_email'];
                        }
                        $daysTillSecondSurveyReminder = DAYS_TILL_SECOND_SURVEY_REMINDER_DEFAULT;
                        if (isset($this->pluginOptions['limesurvey_days_till_second_survey_email_reminder']) && $this->pluginOptions['limesurvey_days_till_second_survey_email_reminder'] != '') {
                            $daysTillSecondSurveyReminder = $this->pluginOptions['limesurvey_days_till_second_survey_email_reminder'];
                        }
                        $daysTillThirdSurvey = DAYS_TILL_THIRD_SURVEY_DEFAULT;
                        if (isset($this->pluginOptions['limesurvey_days_till_third_survey_email']) && $this->pluginOptions['limesurvey_days_till_third_survey_email'] != '') {
                            $daysTillThirdSurvey = $this->pluginOptions['limesurvey_days_till_third_survey_email'];
                        }
                        $daysTillThirdSurveyReminder = DAYS_TILL_THIRD_SURVEY_REMINDER_DEFAULT;
                        if (isset($this->pluginOptions['limesurvey_days_till_third_survey_email_reminder']) && $this->pluginOptions['limesurvey_days_till_third_survey_email_reminder'] != '') {
                            $daysTillThirdSurveyReminder = $this->pluginOptions['limesurvey_days_till_third_survey_email_reminder'];
                        }

                        if ($daysDiff == $daysTillSecondSurvey) {
                            $this->mailReminder(LIMESURVEY_ID_AFTER_TRAINING, $training->getId(), $user, 'limesurvey_second_survey_email');
                        } else if ($daysDiff == ($daysTillSecondSurvey + $daysTillSecondSurveyReminder)) {
                            if (!$this->checkSurvey(LIMESURVEY_ID_AFTER_TRAINING, $training->getId(), $user->ID)) {
                                $this->mailReminder(LIMESURVEY_ID_AFTER_TRAINING, $training->getId(), $user, 'limesurvey_second_survey_email_reminder');
                            }
                        } else if ($daysDiff == $daysTillThirdSurvey) {
                            $this->mailReminder(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $training->getId(), $user, 'limesurvey_third_survey_email');
                        } else if ($daysDiff == ($daysTillThirdSurvey + $daysTillThirdSurveyReminder)) {
                            if (!$this->checkSurvey(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $training->getId(), $user->ID)) {
                                $this->mailReminder(LIMESURVEY_ID_AFTER_TRAINING_CHECK, $training->getId(), $user, 'limesurvey_third_survey_email_reminder');
                            }
                        }
                    }
                }
            }
        }
    }

    private function mailReminder ($fieldId, $trainingsID, $user, $id) {
        $emailData = $this->getReminderEmailSubjectAndBody($id);
        wp_mail($user->user_email, $emailData['subject'], str_ireplace('[survey_link]', $this->surveyUrl($fieldId, $trainingsID, $user->ID), $emailData['body']));
    }

    private function getReminderEmailSubjectAndBody ($id) {
        $secondSurveyEmailXml = new \SimpleXMLElement(file_get_contents(dirname(__FILE__) . '/emails/'.$id.'.xml'));
        $subject = $secondSurveyEmailXml->subject;
        if (isset($this->pluginOptions[$id.'_subject']) && $this->pluginOptions[$id.'_subject'] != '') {
            $subject = $this->pluginOptions[$id.'_subject'];
        }
        $body = $secondSurveyEmailXml->body;
        if (isset($this->pluginOptions[$id.'_body']) && $this->pluginOptions[$id.'_body'] != '') {
            $body = $this->pluginOptions[$id.'_body'];
        }
        return [
            'subject' => $subject,
            'body' => $body,
        ];
    }
}
