<?php

declare(strict_types=1);

namespace mirzaev\site\mirzaev\models;

// Файлы проекта
use mirzaev\site\mirzaev\models\vk_model as vk;

// Фреймворк ArangoDB
use mirzaev\arangodb\collection,
    mirzaev\arangodb\document;

// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;

// Встроенные библиотеки
use exception;

/**
 * Модель регистрации, аутентификации и авторизации
 *
 * @package mirzaev\site\mirzaev\models
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
final class account_model extends core
{
    /**
     * Коллекция
     */
    public const COLLECTION = 'account';

    /**
     * Создать
     *
     * @param array &$errors Журнал ошибок
     *
     * @return ?_document Инстанция аккаунта, если удалось создать
     */
    public static function create(array &$errors = []): ?_document
    {
        try {
            if (collection::init(static::$db->session, self::COLLECTION)) {
                // Инициализирована коллекция

                // Запись аккаунта в базу данных
                $_id = document::write(static::$db->session, self::COLLECTION);

                if ($account = collection::search(static::$db->session, sprintf(
                    <<<AQL
                            FOR d IN %s
                            FILTER d._id == '$_id'
                            RETURN d
                        AQL,
                    self::COLLECTION
                ))) {
                    // Найден созданный аккаунт

                    return $account;
                } else throw new exception('Не удалось создать аккаунт');
            } else throw new exception('Не удалось инициализировать коллекцию');
        } catch (exception $e) {
            // Запись в журнал ошибок
            $errors[] = [
                'text' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'stack' => $e->getTrace()
            ];
        }

        return null;
    }

    /**
     * Связь аккаунта с аккаунтом ВКонтакте
     *
     * @param _document $account Инстанция аккаунта
     * @param _document $vk Инстанция аккаунта ВКонтакте
     * @param array &$errors Журнал ошибок
     *
     * @return bool Статус выполнения
     */
    public static function connect(_document $account, _document $vk, array &$errors = []): bool
    {
        try {
            if (
                collection::init(static::$db->session, self::COLLECTION)
                && collection::init(static::$db->session, vk::COLLECTION)
                && collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
            ) {
                // Инициализированы коллекции

                if (document::write(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, [
                    '_from' => $account->getId(),
                    '_to' => $vk->getId()
                ])) {
                    // Создано ребро: account -> vk

                    return true;
                } else throw new exception('Не удалось создать ребро: account -> vk');
            } else throw new exception('Не удалось инициализировать коллекцию');
        } catch (exception $e) {
            // Запись в журнал ошибок
            $errors[] = [
                'text' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'stack' => $e->getTrace()
            ];
        }

        return false;
    }

    /**
     * Поиск связанного аккаунта ВКонтакте
     *
     * @param _document $account Инстанция аккаунта
     * @param array &$errors Журнал ошибок
     *
     * @return ?_document Инстанция аккаунта, если удалось найти
     */
    public static function vk(_document $account, array &$errors = []): ?_document
    {
        try {
            if (
                collection::init(static::$db->session, self::COLLECTION)
                && collection::init(static::$db->session, vk::COLLECTION)
                && collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
            ) {
                // Инициализирована коллекция

                if ($vk = collection::search(static::$db->session, sprintf(
                    <<<AQL
                        FOR document IN %s
                        LET edge = (
                            FOR edge IN %s
                            FILTER edge._from == '%s'
                            SORT edge._key DESC
                            LIMIT 1
                            RETURN edge
                        )
                        FILTER document._id == edge[0]._to
                        LIMIT 1
                        RETURN document
                    AQL,
                    vk::COLLECTION,
                    self::COLLECTION . '_edge_' . vk::COLLECTION,
                    $account->getId()
                ))) {
                    // Найден аккаунт ВКонтакте

                    return $vk;
                } else throw new exception('Не удалось найти аккаунт ВКонтакте');
            } else throw new exception('Не удалось инициализировать коллекцию');
        } catch (exception $e) {
            // Запись в журнал ошибок
            $errors[] = [
                'text' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'stack' => $e->getTrace()
            ];
        }

        return null;
    }
}
