<?php

declare(strict_types=1);

namespace app\models\traits;

use yii;

use exception;

trait SearchByAccount
{
    /**
     * Поиск через связи рёбрами с аккаунтом
     *
     * @param string $id Идентификатор пользователя
     * @param int $limit Количество
     * @param int $offset Сдвиг
     * @param string $sort Сортировка
     */
    public static function searchByAccount(
        string $id = null,
        int $limit = 10,
        int $offset = 0,
        array $sort = ['ASC'],
        string|array $where = [],
        string|array $post_where = [],
        string $direction = 'ANY',
        array $let = [],
        array $params = []
    ): ?array {
        if (!isset($id)) {
            $id = yii::$app->user->id ?? throw new exception('Не найден идентификатор');
        }

        $subquery = static::find()
            ->for(['account', 'account_edge_' . self::collectionName()])
            ->traversal(self::collectionName(), $direction)
            ->in('account_edge_' . self::collectionName())
            ->where(['account._id' => $id]);

        if (!empty($where)) {
            // Переданы дополнительные условия фильтрации

            $subquery->where($where);
        }

        $subquery = $subquery->select('account_edge_' . self::collectionName())
            ->createCommand();

        $query = static::find()
            ->params($params, $subquery->getBindVars())
            ->let('account_edge_' . self::collectionName(), '(' . (string) $subquery . ')')
            ->limit($limit)
            ->offset($offset)
            ->orderBy($sort);

        if (!empty($let)) {
            // Переданы дополнительные условия фильтрации

            $query->let(...$let);
        }

        if (isset($post_where) && $post_where) {
            // Если переданы дополнительные условия фильтрации

            $query->where($post_where);
        } else {
            $query->where(self::collectionName() . '._id == account_edge_' . self::collectionName() . '[0]._to');
        }

        return $query->select(self::collectionName())->all();
    }
}
