<?php

declare(strict_types=1);

namespace app\controllers;

use app\models\AccountEdgeNotification;
use yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;

use app\models\Notification;

class NotificationController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'only' => ['index'],
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@']
                    ]
                ]
            ]
        ];
    }

    /**
     * @todo Перенести логику в модель
     */
    public function actionIndex()
    {
        if (yii::$app->request->isPost) {
            // POST-запрос

            // Инициализация
            $model = new Notification(yii::$app->request->post('Notification'));

            yii::$app->response->format = Response::FORMAT_JSON;

            $return = [
                '_csrf' => yii::$app->request->getCsrfToken()
            ];

            if (yii::$app->request->post('last')) {
                // Запрос последнего уведомлений (всплывающее окно)

                $limit = 1;
            } else if (yii::$app->request->post('stream')) {
                // Запрос последних уведомлений (панель)

                $limit = 5;
            }

            if (isset($limit)) {
                // Обработка для всплывающего окна или панель

                // Подзапрос для проверки статуса уведомления относительно пользователя
                // Поиск рёбер: ПОЛЬЗОВАТЕЛЬ -> УВЕДОМЛЕНИЕ
                $let = $model::find()
                    ->for(['account', $model::collectionName() . '_edge_account'])
                    ->traversal($model::collectionName(), 'OUTBOUND')
                    ->in('account_edge_' . $model::collectionName())
                    ->where(['account._id' => yii::$app->user->id])
                    ->select($model::collectionName() . '_edge_account');

                if (yii::$app->request->post('last')) {
                    // Запрос последнего уведомлений (всплывающее окно)

                    // Уведомление которое не выводилось на мониторе пользователя
                    $type = 'received';
                } else if (yii::$app->request->post('stream')) {
                    // Запрос последних уведомлений (панель)

                    // Уведомление которое не было прочитано в окне уведомний
                    $type = 'checked';
                }

                // Генерация подзапроса по перебору ядра
                $let = $let->createCommand();

                /**
                 * Поиск рёбер: (УВЕДОМЛЕНИЕ)? -> ПОЛЬЗОВАТЕЛЬ
                 *
                 * @param bool $check Активация проверки на то, что уведомление не получено
                */
                $search = function (bool $check = false) use ($model, $type, $let, $limit): array {
                    return $model::searchByEdge(
                        from: 'account',
                        to: 'notification',
                        params: $check ? $let->getBindVars() : [],
                        subquery_where: [
                            [
                                'account._id' => yii::$app->user->id
                            ],
                            [
                                [
                                    'notification.html' => null
                                ],
                                'operator' => '!='
                            ],
                            [
                                'account_edge_notification.type' => $type
                            ]
                        ],
                        let: [
                            'notification_edge_account',
                            '(' . (string) $let . ')'
                        ],
                        where: $check ? [
                            'account_edge_notification[0]._to' => null
                        ] : [],
                        limit: $limit,
                        sort: ['DESC'],
                        direction: 'INBOUND'
                    );
                };

                // Поиск непрочитанных уведомлений пользователя
                $notifications = $search(true);

                if (!yii::$app->request->post('last') && empty($notifications)) {
                    // Уведомления не найдены и запрошены НЕ всплывающие уведомления

                    // Поиск уведомлений пользователя
                    $notifications = $search();
                }

                if (empty($notifications)) {
                    // Уведомления не найдены

                    yii::$app->response->statusCode = 100;

                    goto end;
                }

                foreach ($notifications as $notification) {
                    // Перебор найденных уведомлений

                    // Запись ребра: ПОЛЬЗОВАТЕЛЬ -> УВЕДОМЛЕНИЕ (о том, что уведомление прочитано)
                    AccountEdgeNotification::write(yii::$app->user->id, $notification->readId(), $type);
                }

                if (yii::$app->request->post('last')) {
                    // Запрос последнего уведомлений (всплывающее окно)

                    // Реинициализация
                    $notification = $notifications[0];

                    $return['popup'] = [
                        'html' => $this->renderPartial('popup', compact('model', 'notification')),
                        'id' => 'popup/' . $notification->readId()
                    ];
                } else if (yii::$app->request->post('stream')) {
                    // Запрос последних уведомлений (панель)

                    $return['panel'] = $this->renderPartial('panel', compact('model', 'notifications'));
                }
            } else {
                // Иначе обрабатывается как запрос страницы уведомлений

                $return['main'] = $this->renderPartial('index', compact('model'));
                $return['redirect'] = '/notification';
            }

            end:
            return $return;
        }

        return $this->render('index', ['model' => new Notification(yii::$app->request->get('Notification'))]);
    }
}
