<?php

namespace App\Services;

use App\Exceptions\TencentImException;
use App\Models\ChatTeam;
use App\Models\TencentImGroup;
use App\Models\User;
use App\Traits\TencentIm;

class TencentImGroupService
{
    use TencentIm;

    const TENCENT_REST_APIS = [
        'get_appid_group_list' => 'v4/group_open_http_svc/get_appid_group_list',//获取 App 中的所有群组
        'create_group' => 'v4/group_open_http_svc/create_group',//创建群组
        'get_group_info' => 'v4/group_open_http_svc/get_group_info',//获取群详细资料
        'get_group_member_info' => 'v4/group_open_http_svc/get_group_member_info',//获取群成员详细资料
        'modify_group_base_info' => 'v4/group_open_http_svc/modify_group_base_info',//修改群基础资料
        'add_group_member' => 'v4/group_open_http_svc/add_group_member',//增加群成员
        'delete_group_member' => 'v4/group_open_http_svc/delete_group_member',//删除群成员
        'modify_group_member_info' => 'v4/group_open_http_svc/modify_group_member_info',//修改群成员资料
        'destroy_group' => 'v4/group_open_http_svc/destroy_group',//解散群组
        'get_joined_group_list' => 'v4/group_open_http_svc/get_joined_group_list',//获取用户所加入的群组
        'get_role_in_group' => 'v4/group_open_http_svc/get_joined_group_list',//查询用户在群组中的身份
        'forbid_send_msg' => 'v4/group_open_http_svc/forbid_send_msg',//批量禁言和取消禁言
        'get_group_shutted_uin' => 'v4/group_open_http_svc/get_group_shutted_uin',//获取被禁言群成员列表

        'send_group_msg' => 'v4/group_open_http_svc/send_group_msg',//在群组中发送普通消息

        'send_group_system_notification' => 'v4/group_open_http_svc/send_group_system_notification',//在群组中发送系统通知
        'group_msg_recall' => 'v4/group_open_http_svc/group_msg_recall',//撤回群消息
        'change_group_owner' => 'v4/group_open_http_svc/change_group_owner',//转让群主
        'import_group' => 'v4/group_open_http_svc/import_group',//导入群基础资料
        'import_group_msg' => 'v4/group_open_http_svc/import_group_msg',//导入群消息
        'import_group_member' => 'v4/group_open_http_svc/import_group_member',//导入群成员
        'set_unread_msg_num' => 'v4/group_open_http_svc/set_unread_msg_num',//设置成员未读消息计数
        'delete_group_msg_by_sender' => 'v4/group_open_http_svc/delete_group_msg_by_sender',//删除指定用户发送的消息
        'group_msg_get_simple' => 'v4/group_open_http_svc/group_msg_get_simple',//拉取群历史消息
        'get_online_member_num' => 'v4/group_open_http_svc/get_online_member_num',//获取直播群在线人数


        'createGroup' => 'v4/group_open_http_svc/create_group',     //创建群组 支持同时创建多个
        'getGroupList' => 'v4/group_open_http_svc/get_appid_group_list', //获取app中所有群组
    ];

    public static $instance;

    //获取实例
    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 获取所有 APP 中的群组
     * @param int $limit
     * @param int $next
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getGroupList(int $limit = 10000, int $next = 0)
    {
        $this->restApiName = self::TENCENT_REST_APIS['getGroupList'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'Limit' => $limit,
            'Next' => $next
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;

    }

    /**
     * @param array $createData
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * 创建群聊
     */
    public function createGroup(array $createData)
    {
        $this->restApiName = self::TENCENT_REST_APIS['createGroup'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        //组装群成员
        $member_list = array();
        foreach ($createData['member_list'] as $k => $v) {
            $member_list [] = ['Member_Account' => $v['tencent_im_user_id']];
        }
        $createData['group_name'] = mb_substr($createData['group_name'], 0, 30);
        //TODO 做单点登录，避免并发
        $params = [
            //TODO 新建群默认群主为APP管理员
            'Owner_Account' => $createData['Owner_Account'],//群主账户
            'Type' => 'Public',
            'Name' => $createData['group_name'], //群名称
            'FaceUrl' => $createData['avatar'], //群头像
            "MemberList" => $member_list,
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 获取群详细资料
     * @param $group_id
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getGroupInfo($group_id)
    {
        $this->restApiName = self::TENCENT_REST_APIS['get_group_info'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();

        $params = [
            'GroupIdList' => [$group_id],
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 获取群成员详细资料
     * @param $group_id
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getGroupMemberInfo($group_id)
    {
        $this->restApiName = self::TENCENT_REST_APIS['get_group_member_info'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();

        $params = [
            'GroupId' => $group_id,
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 修改群基础资料
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function modifyGroupBaseInfo($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['modify_group_base_info'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();

        $params = array();
        $params['GroupId'] = $data['GroupId']; //必须
        //群名称
        if (isset($data['name']) && !empty($data['name'])) {
            $params['Name'] = $data['name'];
        }
        //群头像
        if (isset($data['FaceUrl']) && !empty($data['FaceUrl'])) {
            $params['FaceUrl'] = $data['FaceUrl'];
        }
        //群简介
        if (isset($data['Introduction']) && !empty($data['Introduction'])) {
            $params['Introduction'] = $data['Introduction'];
        }
        //群公告
        if (isset($data['Notification']) && !empty($data['Notification'])) {
            $params['Notification'] = $data['Notification'];
        }
        //最大群成员数量
        if (isset($data['MaxMemberNum']) && !empty($data['MaxMemberNum'])) {
            $params['MaxMemberNum'] = $data['MaxMemberNum'];
        }
        //申请加群方式
        if (isset($data['ApplyJoinOption']) && !empty($data['ApplyJoinOption'])) {
            $params['ApplyJoinOption'] = $data['ApplyJoinOption'];
        }
        //设置全员禁言（选填）:"On"开启，"Off"关闭
        if (isset($data['ShutUpAllMember']) && !empty($data['ShutUpAllMember'])) {
            $params['ShutUpAllMember'] = $data['ShutUpAllMember'];
        }
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 添加群成员
     * @param $group_id
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function addGroupMember($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['add_group_member'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        //组装群成员
        $member_list = array();
        foreach ($data['member_list'] as $k => $v) {
            $member_list [] = ['Member_Account' => $v['tencent_im_user_id']];
        }
        $params = [
            'GroupId' => $data['GroupId'],
            //"Silence"=> 1, //静默加人
            'MemberList' => $member_list,
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);

        $this->updateFaceUrl($data['GroupId']);

        return $apiResult;
    }

    /**
     * 删除群成员
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function deleteGroupMember($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['delete_group_member'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        //组装群成员
        $member_list = array();
        foreach ($data['member_list'] as $k => $v) {
            $member_list [] = $v['tencent_im_user_id'];
        }
        $params = [
            'GroupId' => $data['GroupId'],
            'Silence' => 1, //静默删人
            'MemberToDel_Account' => $member_list,
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);

        $this->updateFaceUrl($data['GroupId']);

        return $apiResult;
    }

    /**
     * 解散群
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function destroyGroup($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['destroy_group'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'GroupId' => $data['GroupId']
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);

        return $apiResult;
    }

    /**
     * 获取用户所加入的群组
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getJoinedGroupList($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['get_joined_group_list'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'Member_Account' => $data['tencent_im_user_id'],
            "GroupType" => "Public",
            "Limit"=> 10, // 拉取多少个，不填标识拉取全部
            //"Offset"=> 0 // 从第多少个开始拉取
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 查询用户在群组中的身份
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getRoleInGroup($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['get_role_in_group'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        //组装群成员
        $member_list = array();
        foreach ($data['member_list'] as $k => $v) {
            $member_list [] = $v['tencent_im_user_id'];
        }
        $params = [
            'GroupId' => $data['GroupId'],
            'User_Account' => $member_list,
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 批量禁言和取消禁言
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function forbidSendMsg($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['forbid_send_msg'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        //组装群成员
        $member_list = array();
        foreach ($data['member_list'] as $k => $v) {
            $member_list [] = $v['tencent_im_user_id'];
        }
        $params = [
            'GroupId' => $data['GroupId'],
            'Members_Account' => $member_list,
            'ShutUpTime' => $data['ShutUpTime'], //禁言时间 单位秒   0表示取消禁言
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 获取被禁言群成员列表
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getGroupShuttedUin($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['get_group_shutted_uin'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'GroupId' => $data['GroupId'],
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 发消息
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function sendGroupMsg($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['send_group_msg'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'GroupId' => $data['GroupId'],
            'Random' => time(), //无符号32位整数 随机值
            'MsgBody' => $data['MsgBody'],
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 在群组中发送系统通知
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function sendGroupSystemNotification($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['send_group_system_notification'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'GroupId' => $data['GroupId'],
            'Content' => $data['content'],
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 转让群主
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function changeGroupOwner($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['change_group_owner'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'GroupId' => $data['GroupId'],
            'NewOwner_Account' => $data['tencent_im_user_id'],
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 撤回群消息
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function groupMsgRecall($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['group_msg_recall'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'GroupId' => $data['GroupId'],
            'MsgSeqList' => [['MsgSeq' => $data['MsgSeq']]],
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * 拉取群历史消息
     * @param $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function groupMsgGetSimple($data)
    {
        $this->restApiName = self::TENCENT_REST_APIS['group_msg_get_simple'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params['GroupId'] = $data['GroupId'];
        $params['ReqMsgNumber'] = $data['number']; //拉取的历史消息的条数，目前一次请求最多返回20条历史消息，所以这里最好小于等于20
        if (isset($data['seq']) && !empty($data['seq'])) {
            $params['ReqMsgSeq'] = $data['seq']; //拉取消息的最大 seq
        }
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult;
    }

    /**
     * @param $ids
     * @return array
     * 获取群聊用户和头像
     */
    public function getUsersAndAvatar($ids)
    {
        $users = User::query()->whereIn('id', $ids)
            ->select(['id', 'name', 'avatar', 'tencent_im_user_id'])
            ->get()->toArray();
        $arr_avatar = array();
        foreach ($users as $k => $v) {
            $arr_avatar[] = $v['avatar'];
        }
        $file_avatar = '/avatar/' . time() . rand(100, 999) . '.png';
        if (GroupAvatar::getGroupAvatar($arr_avatar, true, '.' . $file_avatar)) {
            $file_avatar = "https://" . $_SERVER['HTTP_HOST'] . $file_avatar;
        }
        $data = [
            'users' => $users,
            'file_avatar' => $file_avatar,
        ];
        return $data;
    }

    /**
     * @param $group_id
     * @throws TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * 设置群聊头像(成员变动需要更新群头像)
     */
    public function updateFaceUrl($group_id)
    {
        $res = $this->getGroupInfo($group_id);
        $groupAvatarUrl = $res['GroupInfo'][0]['FaceUrl'];
        if ($res['ErrorCode'] == 0 && !empty($res['GroupInfo'])) {
            if (!empty($res['GroupInfo'][0]['MemberList'])) {
                foreach ($res['GroupInfo'][0]['MemberList'] as &$v) {
                    $user = User::query()->where(['tencent_im_user_id' => $v['Member_Account']])->select('id', 'name', 'avatar')->first();
                    $v['user_id'] = $user->id;
                    $v['name'] = $user->id;
                    $v['avatar'] = $user->avatar;
                }
            }
        }
        $arr_avatar = array_column($res['GroupInfo'][0]['MemberList'], 'avatar');
        $fileName = basename($groupAvatarUrl);
        $fileName = substr($fileName, 0, strpos($fileName, '.'));
        $file_avatar = '/avatar/' . $fileName . '.png';
        GroupAvatar::getGroupAvatar($arr_avatar, true, '.' . $file_avatar);
    }

}
