<?php

class UsersModel_ extends bff\modules\users\Model implements modules\users\Consts
{
    public function init()
    {
        parent::init();

        # список полей данных о пользователе запрашиваемых для сохранения в сессии
        $this->userSessionDataKeys = $this->app->filter('users.model.user.session.data.keys', [
            'user_id as id','member','login','last_login','company_id','social_id','admin',
            'password','password_salt','email','phone_number','phone_number_verified','phone','lang',
            'name','surname','avatar','sex','birthdate','activated','blocked','blocked_reason',
        ]);
    }

    /**
     * Получаем данные о пользователе по ID или фильтру
     * @param array|int $filter фильтр или ID пользователя
     * @param array|string $fields ключи необходимых данных
     * @param bool $edit true - выполнить подготовку данных для редактирования
     * @return array
     */
    public function userData($filter, $fields = [], bool $edit = false): array
    {
        if (! is_array($filter)) {
            $filter = ['user_id' => $filter];
        }

        $data = $this->userDataByFilter($filter, $fields);
        if (empty($data) || ! is_array($data)) {
            return [];
        }

        if ($edit) {
            if (isset($data['geo_city'])) {
                $data['city_title'] = Geo::regionTitle($data['geo_city']);
            }
        }
        if (isset($data['phones']) || (is_array($data) && array_key_exists('phones', $data))) {
            $data['phones'] = (!empty($data['phones']) ? func::unserialize($data['phones']) : []);
        }
        if (isset($data['extra'])) {
            $data['extra'] = func::unserialize($data['extra']);
        }

        return $data;
    }

    /**
     * Данные о пользователях для правого блока по ID или фильтру
     * @param int|array  $filter фильтр или ID пользователя
     * @param array $plus ключи доп. полей
     * @param array $opts доп. параметры
     * @return array
     */
    public function usersDataSidebar($filter, array $plus = [], array $opts = []): array
    {
        $fields = $this->app->filter('users.model.user.data.sidebar', [
            'user_id as id', 'name', 'login', 'last_login', 'last_activity', 'company_id', 'created', 'avatar', 'sex',
            'phones', 'phone_number', 'phone_number_verified', 'contacts',
        ]);
        if (!empty($plus)) {
            $fields = array_merge($fields, $plus);
        }

        $oneUserData = false;
        if (!is_array($filter) && is_numeric($filter)) {
            $filter = ['user_id' => $filter];
            $oneUserData = true;
        }

        $users = $this->usersList($filter, $fields);
        $users = func::array_transparent($users, 'id', true);

        if (!empty($users)) {
            foreach ($users as &$data) {
                $data['link'] = Users::urlProfile($data['login']);
                $data['avatar_block'] = UsersAvatar::block($data['id'], $data);
                $data['avatar'] = UsersAvatar::url($data['id'], $data['avatar'], null, $data['sex']);
                if (isset($data['phones']) || (is_array($data) && array_key_exists('phones', $data))) {
                    $data['phones'] = (!empty($data['phones']) ? func::unserialize($data['phones']) : []);
                }
                if (isset($data['extra'])) {
                    $data['extra'] = func::unserialize($data['extra']);
                }
                # add main phone number to the contact phones (as first one)
                if (Users::registerPhoneContacts() && $data['phone_number'] && $data['phone_number_verified']) {
                    if (!is_array($data['phones'])) {
                        $data['phones'] = [];
                    }
                    array_unshift($data['phones'], [
                        'v' => $data['phone_number'],
                        'm' => Users::phoneMask($data['phone_number']),
                    ]);
                }
            }
            unset($data);
        }

        return ($oneUserData ? reset($users) : $users);
    }

    /**
     * Получаем данные о пользователе - для отправки ему email-уведомления.
     * Проверяем возможно ли отправить письмо пользователю и если нет возвращаем FALSE.
     * @param int $userID ID пользователя
     * @param int $enotifyID ID настройки email-уведомления, 0 - не выполнять проверку настроек уведомлений
     * @param array $fields требуемые данные
     * @return array данные
     */
    public function userDataEnotify($userID, int $enotifyID = 0, array $fields = []): array
    {
        $fields = array_merge($fields, $this->app->filter('users.model.user.data.enotify', [
            'user_id','user_id_ex','name','email','login','blocked','enotify',
            'activated','last_login','lang','fake',
        ]));
        $data = $this->userData($userID, $fields, false);

        do {
            # не нашли такого пользователя
            if (empty($data)) {
                break;
            }
            # заблокирован / неактивирован / сгенерированный
            if ($data['blocked'] || !$data['activated'] || $data['fake']) {
                break;
            }
            if (empty($data['lang'])) {
                $data['lang'] = $this->locale->current();
            }

            return $data;
        } while (false);

        return [];
    }

    /**
     * Удаление пользователей помеченных для удаления
     * @return void
     */
    public function usersCronDelete()
    {
        $avatar = Users::avatar();

        $last = 0;
        $skip = [];
        do {
            $filter = [
                'deleted' => ['>', 0],
                ':last' => ['user_id > :last', ':last' => $last],
            ];
            if ($skip) {
                $filter['user_id'] = ['NOT IN', $skip];
            }
            $data = $this->db->select_rows(static::TABLE_USERS, ['user_id','admin','avatar','deleted'], $filter, 'user_id');
            if (empty($data)) {
                break;
            }
            foreach ($data as $v) {
                $userID = $v['user_id'];
                if ($userID == 1 || ($v['admin'] && $this->userIsSuperAdmin($userID))) {
                    $this->userSave($userID, [
                        'deleted' => 0,
                        'blocked' => 0,
                        'blocked_reason' => '',
                    ]);
                    continue;
                }

                if (! $this->app->filter('users.user.deleting', true, $userID, $data)) {
                    $skip[] = $userID;
                    continue;
                }

                $options = [
                    'initiator' => ($v['deleted'] == Users::DESTROY_BY_OWNER ? 'user' : 'admin'),
                ];
                $this->log(sprintf('Deleted user %s by %s', $userID, $options['initiator']), Logger::INFO);

                $this->controller->fireUserDeleted($userID, $options);

                if ($v['avatar']) {
                    $avatar->setRecordID($userID);
                    $avatar->delete(false, $v['avatar']);
                }
                $this->db->delete(static::TABLE_USERS, ['user_id' => $userID]);
                $this->db->delete(static::TABLE_USERS_STAT, ['user_id' => $userID]);
                $this->db->delete(static::TABLE_USER_IN_GROUPS, ['user_id' => $userID]);
                $this->db->delete(static::TABLE_USERS_SOCIAL, ['user_id' => $userID]);
            }
        } while (! empty($data));
    }

    /**
     * Используется ли шифрование поля phone_number в таблице static::TABLE_USERS
     * @return bool
     */
    public function userPhoneCrypted(): bool
    {
        return in_array('phone_number', $this->cryptUsers);
    }
}