<?php

declare(strict_types=1);

namespace app\controllers;

use yii;
use yii\web\Controller;
use yii\web\Response;
use yii\web\Cookie;
use yii\filters\AccessControl;

use app\models\Account;

class AccountController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'actions' => [
                            'file'
                        ]
                    ],
                    [
                        'allow' => true,
                        'roles' => ['@'],
                        'actions' => [
                            'index',
                            'edit',
                            'regenerate'
                        ]
                    ],
                    [
                        'allow' => true,
                        'actions' => ['accept', 'decline'],
                        'matchCallback' => function ($rule, $action): bool {
                            if (
                                !yii::$app->user->isGuest
                                && (yii::$app->user->identity->type === 'administrator'
                                    || yii::$app->user->identity->type === 'moderator')
                            ) {
                                return true;
                            }

                            return false;
                        }
                    ],
                    [
                        'allow' => false,
                        'roles' => ['?'],
                        'denyCallback' => [$this, 'accessDenied']
                    ]
                ]
            ]
        ];
    }

    public function accessDenied()
    {
        // Инициализация
        $cookies = yii::$app->response->cookies;

        // Запись cookie с редиректом, который выполнится после авторизации
        $cookies->add(new Cookie([
            'name' => 'redirect',
            'value' => yii::$app->request->pathInfo
        ]));

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

            // Настройка
            Yii::$app->response->format = Response::FORMAT_JSON;

            // Генерация ответа
            Yii::$app->response->content = json_encode([
                'main' => $this->renderPartial('/account/index'),
                'redirect' => yii::$app->request->pathInfo,
                '_csrf' => Yii::$app->request->getCsrfToken()
            ]);
        } else if (Yii::$app->request->isGet) {
            // GET-запрос

            $this->redirect('/authentication');
        }
    }

    public function actionIndex()
    {
        return $this->renderPartial('/accounts/index');
    }

    /**
     * Подтверждение
     *
     * @param int $_key Идентификатор аккаунта
     */
    public function actionAccept(string $_key)
    {
        if (yii::$app->user->isGuest) {
            // Аккаунт не аутентифицирован
        } else {
            if (yii::$app->request->isPost) {
                // AJAX-POST-запрос

                if (
                    yii::$app->user->identity->type === 'administrator'
                    || yii::$app->user->identity->type === 'moderator'
                ) {
                    // Запрос произведен уполномоченным

                    if ($account = Account::searchById(Account::collectionName() . '/' . $_key)) {
                        // Аккаунт найден

                        $account->type = 'user';

                        if ($account->update() > 0) {
                            // Удалось перезаписать данные в хранилище

                            // Запись в журнал
                            $account->journal('accepted into suppliers');

                            // Отправка письма с подтверждением аккаунта
                            $account->sendMailVerify();

                            // Настройка формата ответа
                            yii::$app->response->format = Response::FORMAT_JSON;

                            return true;
                        }
                    }
                }
            }
        }

        // Запись кода ответа
        yii::$app->response->statusCode = 500;

        return false;
    }

    /**
     * Отказ
     *
     * @param int $_key Идентификатор аккаунта
     */
    public function actionDecline(string $_key)
    {
        if (yii::$app->user->isGuest) {
            // Аккаунт не аутентифицирован
        } else {
            if (yii::$app->request->isPost) {
                // AJAX-POST-запрос

                if (
                    yii::$app->user->identity->type === 'administrator'
                    || yii::$app->user->identity->type === 'moderator'
                ) {
                    // Запрос произведен уполномоченным

                    if ($account = Account::searchById(Account::collectionName() . '/' . $_key)) {
                        // Аккаунт найден

                        // Отправка письма с отказом и причиной
                        $account->sendMailDecline(yii::$app->request->post('reason') ?? yii::$app->request->get('reason'));

                        // Настройка формата ответа
                        yii::$app->response->format = Response::FORMAT_JSON;

                        // Удаление аккаунта
                        return $account->delete() > 0;
                    }
                }
            }
        }

        // Запись кода ответа
        yii::$app->response->statusCode = 500;

        return false;
    }

    /**
     * Запрос файла
     *
     * @param int $_key Идентификатор аккаунта
     * @param string $file Путь до файла от каталога аккаунта
     */
    public function actionFile(string $_key, string $file)
    {
        // Инициализация файла
        $file = YII_PATH_PUBLIC . "/../assets/accounts/$_key/files/$file";

        if (file_exists($file)) {
            // Удалось найти файл

            return $this->response->sendFile($file);
        } else {
            // Не удалось найти файл

            // Запись кода ответа
            yii::$app->response->statusCode = 500;

            // Перенаправление на страницу аккаунта
            return yii::$app->response->redirect("/$_key");
        }
    }

    /**
     * Редактирование параметра
     *
     * @param int $_key
     * @param string $target
     *
     * @return void
     */
    public function actionEdit(int $_key, string $target)
    {
        if (yii::$app->user->isGuest) {
            // Аккаунт не аутентифицирован
        } else {
            if (yii::$app->request->isPost) {
                // AJAX-POST-запрос

                if (
                    $_key === yii::$app->user->identity->_key ||
                    (yii::$app->user->identity->type === 'administrator'
                        || yii::$app->user->identity->type === 'moderator')
                ) {
                    // Запрос произведен с изменяемого аккаунта, либо уполномоченным

                    if ($account = Account::searchById(Account::collectionName() . '/' . $_key)) {
                        // Аккаунт найден

                        // Запись параметра
                        $account->{$target} = yii::$app->request->post('value') ?? yii::$app->request->get('value') ?? 'Неизвестно';

                        // Настройка формата ответа
                        yii::$app->response->format = Response::FORMAT_JSON;

                        return $account->update() > 0;
                    }
                }
            }
        }

        // Запись кода ответа
        yii::$app->response->statusCode = 500;

        return false;
    }

    /**
     * Регенерация параметра
     *
     * @param int $_key
     * @param string $target
     * @return void
     */
    public function actionRegenerate(int $_key, string $target)
    {
        if (yii::$app->user->isGuest) {
            // Аккаунт не аутентифицирован
        } else {
            if (yii::$app->request->isPost) {
                // AJAX-POST-запрос

                if ($account = Account::searchById(Account::collectionName() . '/' . $_key)) {
                    // Аккаунт найден

                    if (
                        $account->_key === yii::$app->user->identity->_key ||
                        (yii::$app->user->identity->type === 'administrator'
                            || yii::$app->user->identity->type === 'moderator')
                    ) {
                        // Запрос произведен с изменяемого аккаунта, либо уполномоченным

                        if ($target === 'indx') {
                            // Запрошена регенерация индекса

                            // Настройка формата ответа
                            yii::$app->response->format = Response::FORMAT_JSON;

                            // Регенерация индекса
                            return Account::generateIndexes([$account], force: true);
                        }
                    }
                }
            }
        }

        // Запись кода ответа
        yii::$app->response->statusCode = 500;

        return false;
    }
}
