<?php

/**
 * 群组相关
 * @author solu
 */
class GroupInfo extends Model {
    protected $tableName = 'group_info';
    protected $dbKey = 'dw_chat';

    const OFFICIAL_ID = 10000; // 官方群id

    /**
     * 加入群组
     * @author solu
     * @param $userId
     * @param $groupId
     * @param $group
     * @return bool
     * @throws Exception
     */
    public function joinGroup($userId, $groupId, $group = []) {
        $where = ['group_id' => $groupId];
        !$group && $group = $this->objTable->getRow($where);

        if (!$group) {
            throw new Exception('group not exists', CODE_PARAM_ERROR);
        }

        $objUserGroup = new TableHelper('user_group', 'dw_chat');
        if ($objUserGroup->getRow(['user_id' => $userId, 'group_id' => $groupId, 'state' => UserGroup::STATE_IN_GROUP])) {
            throw new Exception('already joined this group', CODE_PARAM_ERROR);
        }

        $objSession = new Session();
        $objUserGroup->autoCommit(false);
        $data = [
            'user_id' => $userId,
            'group_id' => $groupId,
            'join_time' => NOW,
            'state' => UserGroup::STATE_IN_GROUP,
        ];
        if (!$objUserGroup->replaceObject($data)) {
            throw new Exception('join fail', CODE_DB_ERROR);
        }

        $memberNum = $group['member_num'] + 1;
        $where['member_num'] = $group['member_num'];
        if (!$this->objTable->updateObject(['member_num' => $memberNum], $where)) {
            throw new Exception('update group info fail', CODE_DB_ERROR);
        }

        $sessData = [
            'user_id' => $userId,
            'session_id' => $groupId,
            'is_group' => 1,
        ];
        if (!$objSession->objTable->replaceObject($sessData)) {
            throw new Exception('create session error', CODE_DB_ERROR);
        }

        $objUserGroup->commit();

        // 给自己发消息订阅新群组
        ThirdApi::pushPersonEvent($userId, [
            'type' => 'join_group',
            'group_id' => $groupId,
        ]);

        $user_info = User::getUserInfoById($userId);

        // 给群组发消息有人加入了
        ThirdApi::pushGroupEvent($groupId, [
            'type' => 'join',
            'group_id' => $groupId,
            'user_info' => $user_info,
        ]);

        return true;
    }

    /**
     * 加入群组
     * @author solu
     * @param $userId
     * @param $groupId
     * @param $group
     * @return bool
     * @throws Exception
     */
    public function appendToGroup($userIds, $groupId) {
        $userGroupDatas = [];
        $sessDatas = [];

        foreach ($userIds as $userId) {
            $userGroupDatas[] = [
                'user_id' => $userId,
                'group_id' => $groupId,
                'join_time' => NOW,
                'state' => UserGroup::STATE_IN_GROUP,
            ];

            $sessDatas[] = [
                'user_id' => $userId,
                'session_id' => $groupId,
                'is_group' => 1,
            ];
        }
        $objUserGroup = new UserGroup();
        $objUserGroup->objTable->replaceObjects2($userGroupDatas);

        $objSession = new Session();
        $objSession->objTable->replaceObjects2($sessDatas);

        $where = ['group_id' => $groupId];
        $newData = [
            'member_num' => count($userIds),
            'group_name' => $groupId,
        ];
        $this->objTable->updateObject($newData, $where);
    }

    /**
     * 离开群组
     * @author solu
     * @param $userId
     * @param $groupId
     * @param $group
     * @return bool
     * @throws Exception
     */
    public function leaveGroup($userId, $groupId, $group = []) {
        $where = ['group_id' => $groupId];
        !$group && $group = $this->objTable->getRow($where);

        if (!$group) {
            throw new Exception('group not exists', CODE_PARAM_ERROR);
        }

        $objUserGroup = new TableHelper('user_group', 'dw_chat');
        if (!$objUserGroup->getRow(['user_id' => $userId, 'group_id' => $groupId, 'state' => UserGroup::STATE_IN_GROUP])) {
            throw new Exception('not in group', CODE_PARAM_ERROR);
        }

        $objSession = new Session();
        $objUserGroup->autoCommit(false);

        $ugWhere = [
            'user_id' => $userId,
            'group_id' => $groupId,
        ];
        if (!$objUserGroup->updateObject(['state' => UserGroup::STATE_LEAVE], $ugWhere)) {
            throw new Exception('leave fail', CODE_DB_ERROR);
        }

        $memberNum = $group['member_num'] - 1;
        $where['member_num'] = $group['member_num'];
        if (!$this->objTable->updateObject(['member_num' => $memberNum], $where)) {
            throw new Exception('update group info fail', CODE_DB_ERROR);
        }

        $sessWhere = [
            'user_id' => $userId,
            'session_id' => $groupId,
        ];
        if (!$objSession->objTable->delObject($sessWhere)) {
            throw new Exception('delete session error', CODE_DB_ERROR);
        }

        $objUserGroup->commit();

        // 给自己发消息订阅新群组
        ThirdApi::pushPersonEvent($userId, [
            'type' => 'leave_group',
            'group_id' => $groupId,
        ]);

        $user_info = User::getUserInfoById($userId);

        // 给群组发消息有人离开了
        ThirdApi::pushGroupEvent($groupId, [
            'type' => 'leave',
            'group_id' => $groupId,
            'user_id' => $userId,
            'user_info' => $user_info,
        ]);

        return true;
    }

    /**
     * 更新信息
     * @author solu
     * @param $userId
     * @param $groupId
     * @param array $data
     * @return bool|int
     * @throws Exception
     */
    public function setData($userId, $groupId, array $data) {
        if (!(new UserGroup())->isAdmin($groupId, $userId)) {
            throw new Exception('no permission', CODE_NO_PERMITION);
        }

        $data['update_time'] = NOW;
        return $this->objTable->updateObject($data, ['group_id' => $groupId]);
    }

    /**
     * 分享连接
     * @author solu
     * @param string $name
     * @return string
     */
    public static function genInviteUrl($name) {
        if (!$name) {
            return '';
        }

        return sprintf('%s/s/%s', URL_SELF, $name);
    }
}