<?php

declare(strict_types=1);

namespace app\controllers;

use yii;
use yii\web\Controller;
use yii\web\Response;

use app\models\Product;
use app\models\Search;

/**
 * @todo
 * 1. Ограничение доступа
 */
class SearchController extends Controller
{
    /**
     * @todo
     * 1. Сессию привязать к аккаунту и проверку по нему делать, иначе её можно просто сбрасывать
     * 2. Пагинация
     */
    public function actionIndex(): array|string
    {
        // Инициализация параметров
        $auth_only = false;
        $account = yii::$app->user->identity;

        if ($auth_only && yii::$app->user->isGuest) {
            // Если активирован режим "Поиск только аутентифицированным" и запрос пришел не от аутентифицированного


            // Запись кода ответа: 401 (необходима авторизация)
            yii::$app->response->statusCode = 401;

            // Переход к концу обработки
            goto skip_search;
        }

        // Инициализация
        $query = yii::$app->request->post('request') ?? yii::$app->request->get('q');

        if (yii::$app->request->post('type') === 'product' || yii::$app->request->get('type') === 'product') {
            // Поиск по продуктам

            if (yii::$app->request->post('history')) {
                // Запрошена история

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

                return [
                    'panel' => $this->renderPartial('/search/panel', compact('account') + ['history' => true]),
                    '_csrf' => yii::$app->request->getCsrfToken()
                ];
            }

            // Инициализация сессии
            $session = yii::$app->session;

            // Инициализация ответа
            $response = null;

            // Инициализация параметров
            $timer = 0;

            // Период пропуска запросов (в секундах)
            $period = 3;
            $keep_connect = false;
            $sanction = false;
            $sanction_condition = ($session['last_request'] + $period - time()) < $period;
            $sanction_time = 2;
            $query_min = 2;
            $query_max = 20;

            if (isset($session['last_request'])) {
                // Данные о времени последнего запроса не найдены

                if ($sanction && $sanction_condition) {
                    // Наказание за повторный запрос при условии задержки

                    $session['last_request'] += $sanction_time;
                }
            } else {
                // Это первый запрос

                // Инициализация
                $session['last_request'] = time();

                // Пропуск проверок
                goto first_request;
            }

            // Метка: "Повтор обработки поиска" (для создания непрерывного соединения)
            keep_connect_wait:

            // Запись времени последнего запроса и вычисление об истечении таймера
            $timer = $session['last_request'] + $period - time();

            if ($timer > 0) {
                // Время блокировки не истекло

                // Запись кода ответа: 202 (запрос не обработан)
                yii::$app->response->statusCode = 202;

                $return = [
                    'timer' => $timer,
                    'search_line_window_show' => 1,
                    '_csrf' => yii::$app->request->getCsrfToken()
                ];
            } else {
                // Запрос

                // Очистка времени последнего запроса
                unset($session['last_request']);

                // Метка: "Первый запрос"
                first_request:

                if (strlen($query) < $query_min) {
                    // Выход за ограничения длины с недостатком

                    // Пропуск поиска
                    goto skip_query;
                } else if (strlen($query) > $query_max) {
                    // Выход за ограничения длины с превышением

                    // Пропуск поиска
                    goto skip_query;
                }

                // Запись в историю
                Search::write($query);

                $limit = yii::$app->request->isPost ? 10 : 20;

                if ($response = Product::searchByPartialCatn($query, 'active', $limit, [
                    '_key' => '_key',
                    'catn' => 'catn',
                    'prod' => 'prod',
                    // Баг с названием DESC
                    'dscr' => 'dscr',
                    'catg' => 'catg',
                    'imgs' => 'imgs',
                    'name' => 'name',
                    'prod' => 'prod',
                    'dmns' => 'dmns',
                    'stts' => 'stts'
                ])) {
                    // Данные найдены по поиску в полях Каталожного номера

                    // Генерация данных для представления
                    $response = Search::content(products: $response);

                    if (yii::$app->request->isPost) {
                        // POST-запрос

                        // Запись ответа
                        $return = [
                            'panel' => $this->renderPartial('/search/panel', compact('response', 'query')),
                            'search_line_window_show' => 1,
                            '_csrf' => yii::$app->request->getCsrfToken()
                        ];

                        if ((int) yii::$app->request->post('advanced')) {
                            // Полноценный поиск

                            // Запись ответа
                            $return['main'] = $this->renderPartial('/search/index', compact('response', 'query'));
                            $return['search_line_window_show'] = 1;
                            $return['redirect'] = '/search?type=product&q=' . $query;
                        }
                    }
                } else {
                    // Данные не найдены

                    // Запись кода ответа: 404 (запрашиваемые данные не найдены)
                    yii::$app->response->statusCode = 404;
                }
            }

            // Метка: "Пропуск запроса" (для пропуска самого поиска и возврата ответа)
            skip_query:

            if (yii::$app->request->isPost) {
                // POST-запрос

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

                return $return ?? [
                    'panel' => $this->renderPartial('/search/panel'),
                    'search_line_window_show' => 1,
                    '_csrf' => yii::$app->request->getCsrfToken()
                ];
            } else {
                // GET-запрос

                if (empty($return['main']) && $keep_connect && $timer > 0) {
                    // Режим непрерывного соединения

                    // Ожидание
                    sleep($timer);

                    // Повтор обработки
                    goto keep_connect_wait;
                }

                $advanced = true;

                return $this->render('/search/index', compact('response', 'timer', 'advanced', 'query'));
            }
        }

        // Метка: "Пропуск обработки"
        skip_search:

        if (yii::$app->request->isPost) {
            // POST-запрос

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

            return [
                'panel' => $this->renderPartial('/search/panel'),
                'hide' => (int) $auth_only,
                '_csrf' => yii::$app->request->getCsrfToken()
            ];
        } else {
            // GET-запрос

            return $this->render('/search/index');
        }
    }
}
