<?php

declare(strict_types=1);

namespace app\controllers;

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

use app\models\Order;
use app\models\Account;
use app\models\Product;
use app\models\OrderEdgeSupply;
use app\models\AccountEdgeOrder;
use app\models\connection\Dellin;
use app\models\Invoice;
use app\models\Notification;
use app\models\Search;
use app\models\Settings;
use app\models\Supply;
use app\models\SupplyEdgeProduct;

use Codeception\PHPUnit\ResultPrinter\HTML;
use DateTime;
use Exception;
use Throwable;

class OrderController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'],
                        'actions' => [
                            'index',
                            'accept',
                            'write',
                            'delete',
                            'amount-update',
                            'request',
                            'supply-read',
                            'supply-write-stts',
                            'supply-edit-time',
                            'supply-edit-cost',
                            'supply-edit-comm'
                        ]
                    ],
                    [
                        'allow' => false,
                        'roles' => ['?'],
                        'denyCallback' => [$this, 'accessDenied']
                    ]
                ]
            ]
        ];
    }

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

        if (isset(yii::$app->request->referrer)) {
            // Найден HTTP-заголовок REFERRER

            // Инициализация адреса переадресации из HTTP-заголовка referrer
            $redirect = $referrer = trim(parse_url(yii::$app->request->referrer, PHP_URL_PATH) . '?' . parse_url(yii::$app->request->referrer, PHP_URL_QUERY), '/');
        } else {
            // Не найден HTTP-заголовок REFERRER

            // Инициализация адреса переадресации из текущего URI
            $redirect = yii::$app->request->pathInfo;
        }

        // Реинициализация с фильтрацией
        $redirect = match (yii::$app->request->pathInfo) {
            'order/write' => $redirect,
            'order/delete', 'order/amount-update', 'order/request' => 'cart',
            'order/accept', 'order/supply-read', 'order/supply-write-stts', 'order/supply-edit-time', 'order/supply-edit-cost', 'order/supply-edit-comm' => 'orders',
            default => yii::$app->request->pathInfo
        };

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

        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' => '/orders',
                '_csrf' => yii::$app->request->getCsrfToken()
            ]);
        } else if (yii::$app->request->isGet) {
            // GET-запрос

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

    public function actionIndex(string $type = 'all')
    {
        // Инициализация cookie
        $cookies = yii::$app->response->cookies;

        // Инициализация открытой панели ("Модерация", "Мои заказы")
        $window = yii::$app->request->post('window') ?? yii::$app->request->get('window') ?? 'orders_panel_orders';

        // Инициализация данных поиска
        try {
            if ('@last' === $search = yii::$app->request->post('search') ?? yii::$app->request->get('search')) {
                // Запрошено использование прошлых данных

                // Чтение сохраненных данных в cookie
                $search = $cookies->get('search');

                if (empty($search)) {
                    // Переданы неверные данные

                    throw new Exception("Переданы неверные данные \$search: $search", 500);
                }
            } else {
                // Запрошен поиск

                if (empty($search)) {
                    // Переданы неверные данные

                    throw new Exception("Переданы неверные данные \$search: $search", 500);
                }

                // Запись данных в cookie
                $cookies->add(new Cookie([
                    'name' => 'search',
                    'value' => $search
                ]));
            }
        } catch (Exception $e) {
            // Деинициализация (не удалять, отправляется в представление через compact)
            $search = null;
        } finally {
            if (isset($search)) {
                // Запись в историю
                Search::write($search, 'order');
            }
        }

        // Инициализация открытого окна
        try {
            if ('@last' === $type) {
                // Запрошено использование прошлых данных

                // Чтение сохраненных данных в cookie
                $type = $cookies->get('type');

                if (empty($type)) {
                    // Переданы неверные данные

                    throw new Exception("Переданы неверные данные \$type: $type", 500);
                }
            } else {
                // Запрошена сортировка

                if (empty($type)) {
                    // Переданы неверные данные

                    throw new Exception("Переданы неверные данные \$type: $type", 500);
                }

                // Запись данных в cookie
                $cookies->add(new Cookie([
                    'name' => 'type',
                    'value' => $type
                ]));
            }
        } catch (Exception $e) {
            // Реинициализация
            $type = 'all';
        }

        // Инициализация данных периода (от)
        try {
            if ('@last' === $from = yii::$app->request->post('from') ?? yii::$app->request->get('from')) {
                // Запрошено использование прошлых данных

                // Чтение сохраненных данных в cookie
                $from = $cookies->get('from');

                if (empty($from) || !filter_var($from, FILTER_VALIDATE_INT)) {
                    // Переданы неверные данные (необходим unixtime)

                    throw new Exception("Переданы неверные данные \$from: $from", 500);
                }
            } else {
                // Запрошен поиск

                if (empty($from) || !filter_var($from, FILTER_VALIDATE_INT)) {
                    // Переданы неверные данные (необходим unixtime)

                    throw new Exception("Переданы неверные данные \$from: $from", 500);
                }

                // Запись данных в cookie
                $cookies->add(new Cookie([
                    'name' => 'from',
                    'value' => $from
                ]));
            }
        } catch (Exception $e) {
            // Реинициализация
            $from = time() - 604800;
        } finally {
            // Конвертация типа
            $from = (int) $from;
        }

        // Инициализация данных периода (до)
        try {
            if ('@last' === $to = yii::$app->request->post('to') ?? yii::$app->request->get('to')) {
                // Запрошено использование прошлых данных

                // Чтение данных в cookie
                $to = $cookies->get('to');

                if (empty($to) || !filter_var($to, FILTER_VALIDATE_INT)) {
                    // Переданы неверные данные (необходим unixtime)

                    throw new Exception("Переданы неверные данные \$to: $to", 500);
                }
            } else {
                // Запрошен поиск

                if (empty($to) || !filter_var($to, FILTER_VALIDATE_INT)) {
                    // Переданы неверные данные (необходим unixtime)

                    throw new Exception("Переданы неверные данные \$to: $to", 500);
                }

                // Запись данных в cookie
                $cookies->add(new Cookie([
                    'name' => 'to',
                    'value' => $to
                ]));
            }
        } catch (Exception $e) {
            // Реинициализация
            $to = time();
        } finally {
            // Конвертация типа
            $to = (int) $to;
        }

        // Инициализация заказов
        $orders = Order::search(
            type: $type,
            limit: 10,
            page: 1,
            select: '{account_edge_order, order}',
            supplies: true,
            from: $from,
            to: $to,
            search: $search
        );

        // Фильтрация

        if (
            !yii::$app->user->isGuest
            && yii::$app->user->identity->type === 'administrator'
            || yii::$app->user->identity->type === 'moderator'
        ) {
            // Пользователь имеет доступ

            // Инициализация заказов для модератора
            $moderator_orders = self::genOrdersForModeration();
        } else {
            // Пользователь не имеет доступ

            // Инициализация заглушки
            $moderator_orders = null;
        }

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

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

            // Конвертация из UNIXTIME в формат поддерживаемый календарём по спецификации HTML
            $from = DateTime::createFromFormat('U', (string) $from)->format('Y-m-d');
            $to = DateTime::createFromFormat('U', (string) $to)->format('Y-m-d');

            return [
                'main' => $this->renderPartial('/orders/index', compact('orders', 'moderator_orders', 'search', 'from', 'to', 'window')
                    + ['panel' => $this->renderPartial('/orders/search/panel', ['response' => $orders[0]['supplies']])]),
                'title' => 'Заказы',
                'redirect' => '/orders',
                '_csrf' => yii::$app->request->getCsrfToken()
            ];
        }

        return $this->render('/orders/index', compact('orders', 'moderator_orders'));
    }

    /**
     * Подтверждение заказа
     *
     * @param int $_key Ключ записи в коллекции order
     *
     * @return string|array|null
     */
    public function actionAccept(int $_key): string|array|null
    {
        // Инициализация
        $buffer = [];
        $account_edge_order = AccountEdgeOrder::searchByOrder(Order::collectionName() . '/' . $_key, limit: 1)[0];

        // Запись в буфер записи в базу данных
        $account_edge_order->type = 'accepted';

        // Отправка изменений в базу данных
        if ($account_edge_order->save()) {
            // Удалось сохранить изменения

            // Запись в журнал
            Order::searchById($account_edge_order->_to)->journal('accepted');

            // Инициализация
            $orders = Order::search(type: 'all', limit: 10, page: 1, select: '{account_edge_order, order}', supplies: true);
            $moderator_orders = self::genOrdersForModeration();

            // Запись в буфер вывода
            $buffer['main'] = $this->renderPartial('/orders/index', compact('orders', 'moderator_orders'));
        } else {
            // Не удалось сохранить изменения

            yii::$app->response->statusCode = 500;
        }

        // Запись обязательных параметров
        $buffer['_csrf'] = yii::$app->request->getCsrfToken();

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

        return $buffer;
    }

    /**
     * Запись
     */
    public function actionWrite(): string|array|null
    {
        if (yii::$app->request->isPost) {
            // POST-запрос

            // Инициализация входных данных
            $account = yii::$app->user->identity;
            $supply_id = yii::$app->request->post('supply_id');
            $amount = yii::$app->request->post('amount') ?? 1;
            $delivery_type = yii::$app->request->post('delivery_type');

            // Запись настроек ответа в буфер
            yii::$app->response->format = Response::FORMAT_JSON;

            if (empty($supply_id) || empty($delivery_type)) {
                // Не выполнены условия для выполнения

                // 501 Not Implemented
                yii::$app->response->statusCode = 501;
            }

            // Инициализация возврата по умолчанию
            $return = [
                '_csrf' => yii::$app->request->getCsrfToken()
            ];

            // Инициализация корзины
            if (!$model = Order::search($account)) {
                // Корзина не найдена (текущий заказ)

                // Инициализация
                $model = new Order();
                $model->save() or throw new Exception('Не удалось инициализировать заказ');

                // Запись ребра: АККАУНТ -> ЗАКАЗ
                AccountEdgeOrder::write($account->readId(), $model->readId(), 'current') or $model->addError('errors', 'Не удалось инициализировать ребро: АККАУНТ -> ЗАКАЗ');
            }

            // Если запись не удалась, то вернуть код: 500 Internal Server Error
            $model->writeSupply($supply_id, $delivery_type, (int) $amount) or yii::$app->response->statusCode = 500;

            return $return;
        }

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

        return null;
    }

    /**
     * Удаление
     *
     * @todo Разделить логику (для удобства чтения)
     */
    public function actionDelete(): string|array|null
    {
        // Инициализация
        $targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets');
        $page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
        $account = yii::$app->user->identity;
        $order = Order::search();

        if ($targets) {
            // Удаление выбранных целей (удаление из заказа)

            foreach (isset($targets[0]) && is_array($targets[0]) ? $targets : [$targets] as $target) {
                // Унификация входных параметров

                foreach ($target as $catn => $amount) {
                    // Перебор целей

                    // Удаление
                    $order->deleteSupply([$catn => (int) $amount]);
                }
            }
        } else {
            // Целью подразумевается сам заказ (удаление заказа)

            // Инициализация
            $order->stts = 'reserved';

            if ($order->update()) {
                // Запись в журнал
                $order->journal('reserved');

                // Поиск
                $edge = AccountEdgeOrder::searchByVertex($account->readId(), $order->readId(), 'current');

                if (count($edge) > 1) {
                    // Найден более чем 1 заказ

                    return null;
                }

                // Инициализация
                $edge = $edge[0];
                $edge->type = 'reserved';

                // Запись
                $edge->update();

                // Реинициализация
                $order = Order::search();

                if (empty($order)) {
                    // Корзина не инициализирована

                    // Инициализация
                    $order = new Order();
                    $order->save() or throw new Exception('Не удалось инициализировать заказ');

                    // Подключение
                    $order->connect($account);
                }
            }
        }

        // Инициализация содержимого корзины
        $connections = $order->content(10, $page);

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

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

            return [
                'main' => $this->renderPartial('/cart/index', compact('order', 'connections')),
                'title' => 'Корзина',
                'redirect' => '/cart',
                '_csrf' => yii::$app->request->getCsrfToken()
            ];
        }

        return $this->render('/cart/index', compact('order', 'connections'));
    }

    /**
     * Обновление количества товара
     */
    public function actionAmountUpdate(): string|array|null
    {
        // Инициализация
        $targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets');
        $page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
        $account = yii::$app->user;
        $order = Order::search();
        $connections = $order->content(10, $page);

        foreach (isset($targets[0]) && is_array($targets[0]) ? $targets : [$targets] as $target) {
            // Унификация входных параметров

            foreach ($target as $catn => $data) {
                // Перебор целей (переданных объектов в корзине)

                foreach ($data as $type => $amount) {
                    // Перебор данных цели

                    foreach ($connections as $connection) {
                        // Перебор объектов в корзине

                        if ($connection['supply']['catn'] === $catn) {
                            // Цель найдена (продукт)

                            foreach ($connection['order_edge_supply'] as $order_edge_supply) {
                                // Перебор связанных поставок

                                if ($order_edge_supply["dlvr"]["type"] === $type) {
                                    // Цель найдена (поставка)

                                    if ($connection['amount'][$type] > $amount) {
                                        // Запрошено уменьшение количества

                                        // Удаление
                                        $order->deleteSupply([
                                            $catn => [
                                                $type => $connection['amount'][$type] - $amount
                                            ]
                                        ]);
                                    } else if ($connection['amount'][$type] < $amount) {
                                        // Запрошено увеличение количества

                                        // Запись
                                        $order->writeSupply('supply/' . $connection['supply']['_key'], $type, $amount - $connection['amount'][$type]);
                                    }

                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

        // Ренициализация
        $connections = $order->content(10, $page);

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

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

            return [
                'main' => $this->renderPartial('/cart/index', compact('order', 'connections')),
                'title' => 'Корзина',
                'redirect' => '/cart',
                '_csrf' => yii::$app->request->getCsrfToken()
            ];
        }

        return $this->render('/cart/index', compact('order', 'connections'));
    }

    /**
     * Запросить заказ
     */
    public function actionRequest(): string|array|null
    {
        // Инициализация
        $model = Order::search(supplies: true);

        // Поиск ребра
        $edge = AccountEdgeOrder::searchByVertex(yii::$app->user->id, $model->readId(), 'current');

        if (count($edge) > 1) {
            // Найден более чем 1 заказ

            return null;
        }

        // Инициализация
        $edge = $edge[0];

        // Запись
        $edge->type = 'requested';

        if ($edge->update()) {
            // Удалось сохранить изменения

            // Запись в журнал
            $model->journal('requested');

            // Инициализация буфера поставок
            $supplies = [];

            foreach ($model['supplies'] as $supply) {
                $supplies[] = [
                    'title' => $supply['supply']['catn'],
                    'amount' => [
                        'value' => $supply['amount'] ?? 0,
                        'unit' => 'шт'
                    ],
                    'cost' => [
                        'value' => $supply['cost'] ?? 0,
                        'unit' => 'руб'
                    ],
                    'type' => 'supply'
                ];
            }

            Invoice::generate($model->_key, $this->renderPartial('/invoice/order/pattern', [
                'buyer' => [
                    'id' => yii::$app->user->identity->_key,
                    'info' => 'Неизвестно'
                ],
                'order' => [
                    'id' => $model->_key,
                    'date' => $edge->date ?? time(),
                    'entries' => $supplies
                ]
            ]));

            // Отправка уведомлений модераторам
            Notification::_write($this->renderPartial('/notification/system/orders/new', ['id' => $edge->_key]), true, '@auth', Notification::TYPE_MODERATOR_ORDER_NEW);
        }

        return $this->actionIndex();
    }

    /**
     * Генерация данных заказов для модераторов
     *
     * Включает поиск запрошенных заказов и связанных с ними поставках
     *
     * @return array ['order' => array, 'order_edge_account' => array, 'supplies' => array]
     *
     * @todo Уничтожить заменив на Order::search(supplies: true)
     */
    protected static function genOrdersForModeration(int $page = 1): array
    {
        $orders = Order::search(account: '@all', type: 'requested', limit: 10, page: 1, select: '{account_edge_order, order}');

        foreach ($orders as &$order) {
            // Перебор заказов

            $order['supplies'] = Order::searchById($order['order']['_id'])->content(10, $page);
        }

        return $orders;
    }

    /**
     * Чтение инстанции поставки в заказе (order_edge_supply)
     *
     * @param string $catn Артикул поставки
     *
     * @return string|array|null
     */
    public function actionSupplyRead(string $catn): string|array|null
    {
        // Инициализация
        $buffer = [];

        if ($supply = OrderEdgeSupply::searchBySupplyCatn($catn)) {
            // Удалось найти инстанцию поставки

        }

        if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $_key)) {
            // Удалось найти инстанцию поставки

            // Инициализация ребра: ПОСТАВКА -> ТОВАР
            $supply_edge_product = SupplyEdgeProduct::searchBySupplyId($order_edge_supply->_to);

            // Поиск ребра до аккаунта
            $account = Account::searchBySupplyId($order_edge_supply->_to);

            // Поиск привязанного товара
            $product = Product::searchBySupplyId($order_edge_supply->_to);

            try {
                // Инициализация данных геолокации
                try {
                    $from = (int) $account['opts']['delivery_from_terminal'] ?? Settings::search()->delivery_from_default ?? 36;
                } catch (Exception $e) {
                    $from = (int) Settings::search()->delivery_from_default ?? 36;
                }

                try {
                    $to = (int) yii::$app->user->identity->opts['delivery_to_terminal'] ?? 36;
                } catch (Exception $e) {
                    $to = 36;
                }

                // Инициализация доставки
                $delivery = Dellin::calcDeliveryAdvanced(
                    $from,
                    $to,
                    (int) ($product['wght'] ?? 0),
                    (int) ($product['dmns']['x'] ?? 0),
                    (int) ($product['dmns']['y'] ?? 0),
                    (int) ($product['dmns']['z'] ?? 0),
                    avia: $order_edge_supply->dlvr['type'] === 'avia'
                );

                // Инициализация даты отправки
                try {
                    // Взять данные из "arrivalToOspSender" (Дата прибытия на терминал-отправитель)

                    $delivery_send_date = DateTime::createFromFormat('Y-m-d', $delivery['orderDates']['arrivalToOspSender'])->getTimestamp();
                } catch (Throwable $e) {
                    // Взять данные из "pickup" (Дата передачи груза на адресе отправителя)

                    $delivery_send_date = DateTime::createFromFormat('Y-m-d', $delivery['orderDates']['pickup'])->getTimestamp();
                }

                // Инициализация времени доставки
                try {
                    // Доставка по воздуху (подразумевается), данные из "giveoutFromOspReceiver" (Дата и время, с которого груз готов к выдаче на терминале)

                    $delivery_converted = DateTime::createFromFormat('Y-m-d H:i:s', $delivery['orderDates']['giveoutFromOspReceiver'])->getTimestamp();
                } catch (Throwable $e) {
                    // Автоматическая доставка (подразумевается), данные из "arrivalToOspReceiver" (Дата прибытия натерминал-получатель)

                    $delivery_converted = DateTime::createFromFormat('Y-m-d', $delivery['orderDates']['arrivalToOspReceiver'])->getTimestamp();
                }

                // Рассчет времени доставки
                $delivery = ceil(($delivery_converted - ($delivery_send_date ?? 0)) / 60 / 60 / 24) + 1;
            } catch (Exception $e) {
                // var_dump($e->getMessage());
                // var_dump($e->getTrace());
                // var_dump($e->getFile()); die;

                // var_dump(json_decode($e->getMessage(), true)['errors']); die;
            }

            // Запись параметров
            $buffer['cost'] = $order_edge_supply->cost ?? $order_edge_supply->cost = $supply_edge_product[0]['onec']['Цены']['Цена']['ЦенаЗаЕдиницу'];
            $buffer['time'] = $order_edge_supply->time ?? $delivery ?? 0;
            $buffer['comm'] = $order_edge_supply->comm ?? $order_edge_supply->comm = 'Комментарий к заказу';
            $buffer['stts'] = $order_edge_supply->stts ?? $order_edge_supply->stts = 0;
            $buffer['id'] = $order_edge_supply->_key ?? 'Неизвестно';

            $order_edge_supply->save();
        }

        // Запись обязательных параметров
        $buffer['_csrf'] = yii::$app->request->getCsrfToken();

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

        return $buffer;
    }

    /**
     * Запись статуса поставки в заказе (order_edge_supply)
     *
     * @param string $catn Артикул поставки
     *
     * @return string|array|null
     */
    public function actionSupplyWriteStts(string $catn): string|array|null
    {
        // Инициализация
        $stts = yii::$app->request->post('stts') ?? yii::$app->request->get('stts') ?? '';
        $buffer = [];

        if ($supply = OrderEdgeSupply::searchBySupplyCatn($_id = Supply::collectionName() . '/' . $catn)) {
            // Удалось найти инстанцию поставки

            var_dump($supply);
        }

        if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $catn)) {
            // Удалось найти инстанцию поставки

            // Запись в буфер изначальных данных
            $old = $order_edge_supply->stts;

            // Запись в буфер записи в базу данных
            $order_edge_supply->stts = $stts;

            // Отправка в базу данных
            if ($order_edge_supply->save()) {
                // Удалось сохранить изменения

                // Инициализация аккаунта покупателя
                $account = Account::searchById(AccountEdgeOrder::searchByOrder($order_edge_supply->_from)[0]->_from);

                // Отправка уведомления
                Notification::_write($this->renderPartial('/notification/system/orders/edit', ['order' => $order_edge_supply->_from, 'from' => OrderEdgeSupply::convertStatusToRussian($old), 'to' => OrderEdgeSupply::convertStatusToRussian($stts), 'target' => 'Комментарий']), true, $account->_key, Notification::TYPE_NOTICE);

                // Запись в буфер вывода
                $buffer['stts'] = $order_edge_supply->stts;
            } else {
                // Не удалось сохранить изменения

                yii::$app->response->statusCode = 500;
            }
        }

        // Запись обязательных параметров
        $buffer['_csrf'] = yii::$app->request->getCsrfToken();

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

        return $buffer;
    }

    /**
     * Запись цены поставки в заказе (order_edge_supply)
     *
     * @param string $catn Артикул поставки
     *
     * @return string|array|null
     */
    public function actionSupplyEditCost(int $catn): string|array|null
    {
        // Инициализация
        $cost = yii::$app->request->post('cost') ?? yii::$app->request->get('cost');
        $buffer = [];

        if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $catn)) {
            // Удалось найти инстанцию поставки

            // Запись в буфер изначальных данных
            $old = $order_edge_supply->cost;

            // Запись в буфер записи в базу данных
            $order_edge_supply->cost = $cost;

            // Отправка в базу данных
            if ($order_edge_supply->save()) {
                // Удалось сохранить изменения

                // Инициализация аккаунта покупателя
                $account = Account::searchById(AccountEdgeOrder::searchByOrder($order_edge_supply->_from)[0]->_from);

                // Отправка уведомления
                Notification::_write($this->renderPartial('/notification/system/orders/edit', ['order' => $order_edge_supply->_from, 'from' => $old, 'to' => $cost, 'target' => 'Цена']), true, $account->_key, Notification::TYPE_NOTICE);

                // Запись в буфер вывода
                $buffer['cost'] = $order_edge_supply->cost;
            } else {
                // Не удалось сохранить изменения

                yii::$app->response->statusCode = 500;
            }
        }

        // Запись обязательных параметров
        $buffer['_csrf'] = yii::$app->request->getCsrfToken();

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

        return $buffer;
    }

    /**
     * Запись времени доставки поставки в заказе (order_edge_supply)
     *
     * @param int $_key Ключ записи в коллекции order_edge_supply
     *
     * @return string|array|null
     */
    public function actionSupplyEditTime(int $_key): string|array|null
    {
        // Инициализация
        $time = yii::$app->request->post('time') ?? yii::$app->request->get('time');
        $buffer = [];

        if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $_key)) {
            // Удалось найти инстанцию поставки

            // Запись в буфер изначальных данных
            $old = $order_edge_supply->time;

            // Запись в буфер записи в базу данных
            $order_edge_supply->time = $time;

            // Отправка в базу данных
            if ($order_edge_supply->save()) {
                // Удалось сохранить изменения

                // Инициализация аккаунта покупателя
                $account = Account::searchById(AccountEdgeOrder::searchByOrder($order_edge_supply->_from)[0]->_from);

                // Отправка уведомления
                Notification::_write($this->renderPartial('/notification/system/orders/edit', ['order' => $order_edge_supply->_from, 'from' => $old, 'to' => $time, 'target' => 'Дата поставки']), true, $account->_key, Notification::TYPE_NOTICE);

                // Запись в буфер вывода
                $buffer['time'] = $order_edge_supply->time;
            } else {
                // Не удалось сохранить изменения

                yii::$app->response->statusCode = 500;
            }
        }

        // Запись обязательных параметров
        $buffer['_csrf'] = yii::$app->request->getCsrfToken();

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

        return $buffer;
    }

    /**
     * Запись комментария поставки в заказе (order_edge_supply)
     *
     * @param int $_key Ключ записи в коллекции order_edge_supply
     *
     * @return string|array|null
     */
    public function actionSupplyEditComm(int $_key): string|array|null
    {
        // Инициализация
        $comm = yii::$app->request->post('comm') ?? yii::$app->request->get('comm');
        $buffer = [];

        if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $_key)) {
            // Удалось найти инстанцию поставки

            // Запись в буфер изначальных данных
            $old = $order_edge_supply->comm;

            // Запись в буфер записи в базу данных
            $order_edge_supply->comm = $comm;

            // Отправка в базу данных
            if ($order_edge_supply->save()) {
                // Удалось сохранить изменения

                // Инициализация аккаунта покупателя
                $account = Account::searchById(AccountEdgeOrder::searchByOrder($order_edge_supply->_from)[0]->_from);

                // Отправка уведомления
                Notification::_write($this->renderPartial('/notification/system/orders/edit', ['order' => $order_edge_supply->_from, 'from' => $old, 'to' => $comm, 'target' => 'Комментарий']), true, $account->_key, Notification::TYPE_NOTICE);

                // Запись в буфер вывода
                $buffer['comm'] = $order_edge_supply->comm;
            } else {
                // Не удалось сохранить изменения

                yii::$app->response->statusCode = 500;
            }
        }

        // Запись обязательных параметров
        $buffer['_csrf'] = yii::$app->request->getCsrfToken();

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

        return $buffer;
    }
}
