<?php

namespace App\Services;

use App\Exceptions\TencentImAccountException;
use App\Models\User;
use App\Traits\TencentIm;
use Illuminate\Support\Arr;

class TencentImAccountService
{
    use TencentIm;

    const IM_IDENTIFIER_PREFIX = 'IM_USER_';
    const TENCENT_REST_APIS = [
        'accountImport' => 'v4/im_open_login_svc/account_import',  //导入单个帐号
        'multiAccountImport' => 'v4/im_open_login_svc/multiaccount_import', //导入多个帐号
        'accountDelete' => 'v4/im_open_login_svc/account_delete',  //删除帐号
        'accountCheck' => 'v4/im_open_login_svc/account_check',    //查询帐号是否已导入IM
        'kick' => 'v4/im_open_login_svc/kick',  //失效帐号登录态
        'queryState' => 'v4/openim/querystate', //查询帐号在线状态
    ];

    /**
     * 导入单个账号
     * @param User $user
     * @return string
     * @throws TencentImAccountException
     * @throws \App\Exceptions\TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function accountImport(User $user)
    {
        $this->restApiName = self::TENCENT_REST_APIS['accountImport'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = [
            'Identifier' => self::IM_IDENTIFIER_PREFIX . $user->id,
//            'Nick' => $user->nickname ?? null,
//            'FaceUrl' => valid_url($user->avatar)
        ];
        if ($user->nickname) {
            $params = Arr::add($params, 'Nick', $user->nickName);
        }
        if ($user->avatar) {
            $params = Arr::add($params, 'FaceUrl', $user->avatar);
        }
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return self::IM_IDENTIFIER_PREFIX . $user->id;
    }

    /**
     * 导入多个账号
     * @param array $accounts
     * @return array|string[]
     * @throws TencentImAccountException
     * @throws \App\Exceptions\TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function multiAccountImport(array $accounts)
    {
        $this->restApiName = self::TENCENT_REST_APIS['multiAccountImport'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $accounts = array_unique(array_filter($accounts));

        $this->verifyRestApiMaxItem($accounts);

        $accounts = array_map(function ($value) {
            return self::IM_IDENTIFIER_PREFIX . $value;
        }, $accounts);
        $params = [
            'Accounts' => $accounts,
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $accounts;
    }

    /**
     * 删除账号
     * @param array $accounts
     * @return bool
     * @throws TencentImAccountException
     * @throws \App\Exceptions\TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function accountDelete(array $accounts)
    {
        $this->restApiName = self::TENCENT_REST_APIS['accountDelete'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $accounts = array_unique(array_filter($accounts));

        $this->verifyRestApiMaxItem($accounts);

        $accounts = array_map(function ($value) {
            $UserID = $value;
            return compact('UserID');
        }, $accounts);
        $params = [
            'DeleteItem' => $accounts
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return true;
    }

    /**
     * 查询帐号是否已导入IM
     * @param array $accounts
     * @return mixed
     * @throws TencentImAccountException
     * @throws \App\Exceptions\TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function accountCheck(array $accounts)
    {
        $this->restApiName = self::TENCENT_REST_APIS['accountCheck'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $accounts = array_unique(array_filter($accounts));

        $this->verifyRestApiMaxItem($accounts);

        $accounts = array_map(function ($value) {
            $UserID = $value;
            return compact('UserID');
        }, $accounts);
        $params = [
            'CheckItem' => $accounts
        ];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return $apiResult['ResultItem'];
    }


    /**
     * 强制下线
     * @param string $identifier
     * @return bool
     * @throws TencentImAccountException
     * @throws \App\Exceptions\TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function kick(string $identifier)
    {
        $this->restApiName = self::TENCENT_REST_APIS['kick'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $params = ['Identifier' => $identifier];
        $apiResult = $this->requestApi($baseApiHost, $params);
        self::verifyApiResult($apiResult);
        return true;
    }


    /**
     * 获取用户当前的登录状态
     * @param array $accounts
     * @param bool $isDetail
     * @return mixed
     * @throws TencentImAccountException
     * @throws \App\Exceptions\TencentImException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function queryState(array $accounts, bool $isDetail = false)
    {
        $this->restApiName = self::TENCENT_REST_APIS['queryState'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();
        $accounts = array_unique(array_filter($accounts));

        $this->verifyRestApiMaxItem($accounts);

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

    /**
     * 验证接口返回
     * @param $apiResult
     * @return bool
     * @throws TencentImAccountException
     */
    static public function verifyApiResult($apiResult)
    {
        if (!is_array($apiResult)) {
            throw new TencentImAccountException('IM 请求失败');
        }
        if (count(array_diff(['ActionStatus', 'ErrorCode', 'ErrorInfo'], array_keys($apiResult))) > 0) {
            throw new TencentImAccountException('IM 接口返回异常');
        }
        if (($apiResult['ActionStatus'] != 'OK') || ($apiResult['ErrorCode'] != 0)) {
            throw new TencentImAccountException('操作失败:   ' . $apiResult['ErrorInfo']);
        }
        return true;
    }
}
