<?php
/**
 * @property \modelSubscriptions $model
 */
class actionSubscriptionsSubscribe extends cmsAction {

    private $target = [];
    private $subscribe = [];

    private $need_email_confirm, $modal_close, $success_text = false;

    public $request_params = [
        'controller' => [
            'default' => '',
            'rules'   => [
                ['required'],
                ['sysname']
            ]
        ],
        'subject' => [
            'default' => '',
            'rules'   => [
                ['required'],
                ['sysname']
            ]
        ],
        'params' => [
            'default' => [],
            'rules'   => [
                ['subscribe_params']
            ]
        ]
    ];

    public function run() {

        if (!$this->request->isAjax()) {
            return cmsCore::error404();
        }

        $this->target['controller'] = $this->request->get('controller');
        $this->target['subject']    = $this->request->get('subject');
        $this->target['params']     = array_filter($this->request->get('params'));
        $this->target['hash']       = md5(serialize($this->target));

        if (!cmsCore::isControllerExists($this->target['controller']) ||
                !cmsController::enabled($this->target['controller'])) {

            return $this->cms_template->renderJSON([
                'error' => true
            ]);
        }

        // Контроллер подписки
        $controller = cmsCore::getController($this->target['controller'], $this->request);

        if ($this->cms_user->is_logged) {

            $this->subscribe['user_id']       = $this->cms_user->id;
            $this->subscribe['confirm_token'] = string_random(32, $this->cms_user->email);

        } else {

            // если подписка разрешена только авторизованным
            if (!empty($this->options['need_auth'])) {

                return $this->cms_template->renderJSON([
                    'error'         => false,
                    'confirm_title' => LANG_AUTHORIZATION,
                    'confirm_url'   => href_to('auth', 'login')
                ]);
            }

            // ищем куки гостя
            $subscriber_email = cmsUser::getCookie('subscriber_email', 'string', function ($cookie) {
                return trim($cookie);
            });

            if (!$subscriber_email || $this->validate_email($subscriber_email) !== true) {
                $subscriber_email = null;
            }

            $subscriber_name = cmsUser::getCookie('subscriber_name', 'string', function ($cookie) {
                return trim(strip_tags($cookie));
            });

            if (!$subscriber_name) {
                $subscriber_name = null;
            }

            // если нет куки, спрашиваем данные у гостя
            if (!$subscriber_email || !$subscriber_name) {

                $this->modal_close = true;

                $form = $this->getForm('guest');

                // показываем форму гостям
                if (!$this->request->has('email')) {

                    $confirm = $this->cms_template->renderInternal($this, 'guest_form', [
                        'form'   => $form,
                        'params' => $this->target
                    ]);

                    return $this->cms_template->renderJSON([
                        'error'         => false,
                        'confirm_title' => LANG_SBSCR_GUEST_FORM_TITLE,
                        'confirm'       => $confirm
                    ]);
                }

                $guest_data = $form->parse($this->request, true);

                $errors = $form->validate($this, $guest_data);

                if ($errors) {

                    return $this->cms_template->renderJSON([
                        'errors' => $errors
                    ]);
                }

                $subscriber_email = $guest_data['email'];
                $subscriber_name  = $guest_data['name'];

                // нам нужно подтверждение по email
                $this->need_email_confirm = true;

                // если требуется подтверждение
                if (!empty($this->options['guest_email_confirmation'])) {

                    $this->subscribe['is_confirmed'] = null;
                }
            }

            cmsUser::setCookie('subscriber_email', $subscriber_email, 15768000);
            cmsUser::setCookie('subscriber_name', $subscriber_name, 15768000);

            $this->subscribe['guest_email']   = $subscriber_email;
            $this->subscribe['guest_name']    = $subscriber_name;
            $this->subscribe['confirm_token'] = string_random(32, $this->subscribe['guest_email']);
        }

        // проверяем, не подписаны ли
        if (!$this->model->isSubscribed($this->target, $this->subscribe)) {

            // пробуем получить название списка, в хуке по сути есть небольшая валидация
            $subscribe_list_title = $controller->runHook('subscribe_list_title', [$this->target, $this->subscribe], false);

            // Если по какой-то причине получили false, отдаём ошибку
            if($subscribe_list_title === false) {

                return $this->cms_template->renderJSON([
                    'error' => true
                ]);
            }

            if (is_string($subscribe_list_title)) {
                $this->target['title'] = $subscribe_list_title;
            }

            $list_url = $controller->runHook('subscribe_item_url', [$this->target], false);

            if ($list_url) {
                $this->target['subject_url'] = $list_url;
            }

            // подписываем и возвращаем id нового списка, если он ранее не был создан
            list($now_create_list_id, $sid) = $this->model->subscribe($this->target, $this->subscribe);

            cmsEventsManager::hook('subscribe', [$this->target, $this->subscribe, $now_create_list_id, $sid]);

            // уведомляем администраторов о новом списке, если заголовок не опеределён
            if ($now_create_list_id && empty($this->target['title']) && !empty($this->options['admin_email'])) {

                $admin_emails = explode(',', $this->options['admin_email']);

                foreach ($admin_emails as $admin_email) {

                    $this->controller_messages->sendEmail(trim($admin_email), 'subscribe_new_list', [
                        'admin_slist_url' => href_to_abs('admin', 'controllers', ['edit', 'subscriptions', 'list'])
                    ]);
                }
            }

        } else {

            // если уже подписан на такой email, подтверждения подписки не нужно
            if ($this->need_email_confirm) {

                $this->need_email_confirm = false;

                $this->success_text = LANG_SBSCR_GUEST_IS_EXISTS;
            }
        }

        $this->sendConfirmEmail();

        $list_item = $this->model->getSubscriptionItem($this->target['hash']);

        return $this->cms_template->renderJSON([
            'errors'       => false,
            'error'        => false,
            'callback'     => 'successSubscribe',
            'is_subscribe' => 1,
            'count'        => $list_item['subscribers_count'],
            'modal_close'  => $this->modal_close,
            'success_text' => $this->success_text
        ]);
    }

    private function sendConfirmEmail() {

        // если требуется подтверждение
        if (!empty($this->options['guest_email_confirmation']) && $this->need_email_confirm) {

            $this->success_text = LANG_SBSCR_GUEST_EMAIL_CONFIRM_SEND;

            $to     = ['email' => $this->subscribe['guest_email'], 'name' => $this->subscribe['guest_name']];
            $letter = ['name' => 'subscriptions_guest_confirm'];

            $this->controller_messages->sendEmail($to, $letter, [
                'nickname'      => $this->subscribe['guest_name'],
                'page_url'      => href_to_abs('subscriptions', 'guest_confirm', $this->subscribe['confirm_token']),
                'confirm_token' => $this->subscribe['confirm_token'],
                'valid_until'   => html_date(date('d.m.Y H:i', time() + ($this->options['verify_exp'] * 3600)), true)
            ]);
        }

    }

}
