<?php

declare(strict_types=1);

namespace app\models;

use yii;
use yii\web\IdentityInterface;

use app\models\traits\SearchByEdge;

use Exception;

/**
 * Поиск
 *
 * @see Product Поиск по товарам
 */
class Notification extends Document
{
    use SearchByEdge;

    /**
     * Сценарий для доверенного пользователя с созданием уведомления
     */
    const SCENARIO_TRUSTED_CREATE = 'create';

    /**
     * Цель для отправки уведомления
     *
     * Расшифровывается как $target
     *
     * @see SCENARIO_TRUSTED_CREATE
     */
    public IdentityInterface|string|array|null $trgt;

    /**
     * Текст уведомления
     */
    public string $text;

    /**
     * Типы уведомлений
     */
    public array $typs = [
        'notice' => 'Уведомление',
        'warning' => 'Предупреждение'
    ];

    /**
     * Имя коллекции
     */
    public static function collectionName(): string
    {
        return 'notification';
    }

    /**
     * Свойства
     */
    public function attributes(): array
    {
        return array_merge(
            parent::attributes(),
            [
                'html',
                'type'
            ]
        );
    }

    /**
     * Метки свойств
     */
    public function attributeLabels(): array
    {
        return array_merge(
            parent::attributeLabels(),
            [
                'html' => 'HTML',
                'type' => 'Тип',
                'trgt' => 'Получатели',
                'text' => 'Текст',
            ]
        );
    }

    /**
     * Правила
     */
    public function rules(): array
    {
        return array_merge(
            parent::rules(),
            [
                [
                    'html',
                    'required'
                ],
                [
                    'type',
                    'default',
                    'value' => 'notice'
                ]
            ]
        );
    }

    /**
     * Запись
     *
     * @param string $html HTML уведомления
     * @param IdentityInterface $trgt Получатель уведомления
     * @param string $type Тип уведомления
     *
     * @todo Создать параметр разделителя для администрации
     */
    public function write(string $html = null, IdentityInterface|array|string $trgt = null, string $type = 'notice'): self|array|null
    {
        // Инициализация
        $html ?? $html = $this->html ?? throw new Exception('Не удалось инициализировать содержимое');
        $trgt ?? $trgt = yii::$app->user ?? throw new Exception('Не удалось инициализировать получателя');
        $type ?? $trgt = $this->type ?? throw new Exception('Не удалось инициализировать тип');

        // Инициализация уведомления
        if (isset($html) && (bool) (int) $html) {
            // Получен текст в формете HTML-кода

            $this->html = $this->text ?? null;
        } else {
            // Получен необработанный текст

            $text = htmlspecialchars(strip_tags($this->text ?? null));

            $this->html = <<<HTML
                <p class="my-2 mx-3">$text</p>
            HTML;
        }

        if ($this->save()) {
            // Уведомление записано

            // Инициализация получателей и создание ребра
            if (empty($trgt)) {
                // Получатель не передан

                goto test;
            } else if (is_string($trgt)) {
                // Передана необработанная строка

                // Инициализация
                $delimiter = ',';

                // Конвертация
                $trgt = array_map('trim', explode($delimiter, $trgt));


                if (in_array('@all', $trgt, true)) {
                    // Найден флаг обозначающий отправку всем пользователям

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

                    foreach (Account::readAll() as $target) {
                        // Перебор всех аккаунтов

                        // Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
                        $return[] = AccountEdgeNotification::writeSafe($this->readId(), $target->readId(), $type) ? $this : null;
                    }

                    return $return ? $return : null;
                }

                if (in_array('@test', $trgt, true)) {
                    // Найден флаг обозначающий тестирование (отправка самому себе)

                    test:
                    return AccountEdgeNotification::writeSafe($this->readId(), yii::$app->user->id, $type) ? $this : null;
                }
            }

            if (is_array($trgt)) {
                // Несколько получателей

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

                foreach ($trgt as $target) {
                    // Перебор получателей

                    if ($target instanceof Account) {
                        // Один получатель

                        // Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
                        return AccountEdgeNotification::writeSafe($this->readId(), $target->readId(), $type) ? $this : null;
                    }

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

                        echo ($target->readId()) . "\n";

                        // Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
                        $return[] = AccountEdgeNotification::writeSafe($this->readId(), $target->readId(), $type) ? $this : null;
                    }
                }

                return $return ? $return : null;
            } else if ($trgt instanceof Account) {
                // Один получатель

                // Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
                return AccountEdgeNotification::writeSafe($this->readId(), $trgt->readId(), $type) ? $this : null;
            }
        }

        return null;
    }
}
