<?php


namespace App\Services;


use App\Exceptions\TencentImException;
use App\Exceptions\TencentImGroupException;
use App\Models\TencentImGroup;
use App\Traits\TencentIm;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TencentImGroupService
{
    use TencentIm;

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


    const IM_GROUP_RAW_TYPE_PUBLIC = 'Public';  //陌生人社交群
    const IM_GROUP_RAW_TYPE_Private = 'Private';  //即 Work，好友工作群
    const IM_GROUP_RAW_TYPE_ChatRoom = 'ChatRoom';  //即 Meeting，会议群
    const IM_GROUP_RAW_TYPE_AVChatRoom = 'AVChatRoom';  //直播群

    const IM_GROUP_RAW_TYPE_TIPS = [
        self::IM_GROUP_RAW_TYPE_PUBLIC => '陌生人交友群',
        self::IM_GROUP_RAW_TYPE_Private => '好友工作群',
        self::IM_GROUP_RAW_TYPE_ChatRoom => '会议群',
        self::IM_GROUP_RAW_TYPE_AVChatRoom => '直播群',
    ];

    /**
     * 获取所有 APP 中的群组
     * @param int $limit
     * @param int $next
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \App\Exceptions\TencentImAccountException
     * @throws \App\Exceptions\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 string $groupType
     * @return bool
     * @throws TencentImGroupException
     */
    static public function verifyImGroupType(string $groupType)
    {
        if (!array_key_exists($groupType, TencentImGroup::IM_GROUP_RAW_TYPE_TIPS)) {
            throw new TencentImGroupException('群类型不存在');
        }
        return true;
    }

    /**
     * 验证当日建群上限，并返回当前可以添加的数量
     * @return int
     * @throws TencentImGroupException
     */
    static public function verifyToDayCreateCount()
    {
        if (TencentImGroup::getToDayCreateCount() >= TencentImGroup::IM_GROUP_CREATE_DAY_MAX) {
            throw new TencentImGroupException('单日新建群组上限为: ' . TencentImGroup::IM_GROUP_CREATE_DAY_MAX);
        }
        return (TencentImGroup::IM_GROUP_CREATE_DAY_MAX - TencentImGroup::getToDayCreateCount());
    }

    /**
     * 验证当月建群上限，并返回可以添加的数量
     * @return int
     * @throws TencentImGroupException
     */
    static public function verifyMonthCreateCount()
    {
        if (TencentImGroup::getMonthCreateCount() >= TencentImGroup::IM_GROUP_CREATE_MONTH_MAX) {
            throw new TencentImGroupException('单月新建群组上限为: ' . TencentImGroup::IM_GROUP_CREATE_MONTH_MAX);
        }
        return (TencentImGroup::IM_GROUP_CREATE_MONTH_MAX - TencentImGroup::getMonthCreateCount());
    }

    /**
     * 验证是否可以添加群
     * @param int $groupCount
     * @throws TencentImGroupException
     */
    static public function verifyIsCreateGroup(int $groupCount)
    {
        //验证单次最低
        if ($groupCount < TencentImGroup::IM_GROUP_ONCE_CREATE_MIN) {
            throw new TencentImGroupException('单次添加最低' . TencentImGroup::IM_GROUP_ONCE_CREATE_MIN . ' 个群');
        }

        //验证单次最多
        if ($groupCount > TencentImGroup::IM_GROUP_ONCE_CREATE_MAX) {
            throw new TencentImGroupException('单次添加最多' . TencentImGroup::IM_GROUP_ONCE_CREATE_MAX . ' 个群');
        }
        //验证当天添加群数量
        $canToDayCount = self::verifyToDayCreateCount();
        //验证当月添加上限
        $canMonthCount = self::verifyMonthCreateCount();

        if ($groupCount > $canToDayCount) {
            throw new TencentImGroupException('当前创建数量超过日上限,当日还可创建 ' . $canToDayCount . '个');
        }

        if ($groupCount > $canMonthCount) {
            throw new TencentImGroupException('当前创建数量超过月上限,当月还可创建 ' . $canMonthCount . '个');
        }
        return true;
    }

    /**
     *
     * @param int $groupCount
     * @param string $groupType
     * @throws TencentImGroupException
     * @throws \App\Exceptions\TencentImException
     */
    public function createGroups(int $groupCount, string $groupType = TencentImGroup::DEFAULT_IM_RAW_GROUP_TYPE)
    {


        try {

            //验证群类型是否存在
            self::verifyImGroupType($groupType);

            //是否可以创建群
            self::verifyIsCreateGroup($groupCount);

            DB::beginTransaction();

            $this->restApiName = self::TENCENT_REST_APIS['createGroup'];
            $baseApiHost = $this->getTencentImRestApiBaseHost();

            //TODO 做单点登录，避免并发
            $groupStartIndex = TencentImGroup::getGroupIndex();

            $groupEndIndex = $groupStartIndex + $groupCount;
            for ($i = $groupStartIndex; $i < $groupEndIndex; $i++) {
                $item = [
                    //TODO 新建群默认群主为APP管理员
                    'Owner_Account' => config('im.identifier'),
                    'Type' => TencentImGroup::IM_GROUP_RAW_TYPE_ChatRoom,
                    'Name' => (string)$i,
                ];
                $apiResult = $this->requestApi($baseApiHost, $item);
                self::verifyApiResult($apiResult);
                $item['GroupId'] = $apiResult['GroupId'];
                $item['groupIndex'] = $i;
                $params[] = $item;

            }
            unset($item);

            if (count($params) != $groupCount) {
                throw new TencentImGroupException('添加群组失败!');
            }

            $params = array_map(function ($value) {
                return [
                    'group_name' => $value['Name'],
                    'im_group_raw_id' => $value['GroupId'] ?? $value['groupIndex'],
                    'group_owner_user_id' => null,
                    'im_group_owner_raw_user_id' => $value['Owner_Account'],
                    'group_type' => null,
                    'im_group_raw_type' => $value['Type'],
                    'is_use' => TencentImGroup::UN_USE,
                    'bind_system_im_group_id' => null,
                    'group_index' => $value['groupIndex'] ?? 0,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ];
            }, $params);

            if (!TencentImGroup::insert($params)) {
                Log::log(date('Y-m-d H:i:s', time()) . '创建IM群组,写入系统记录失败', $params);
                throw new TencentImGroupException('创建IM群写入系统记录失败,请联系管理员检查');
            }

            DB::commit();
            return true;
        } catch (TencentImGroupException $e) {
            DB::rollBack();
            return ['error' => $e->getMessage()];
        } catch (TencentImException  $e) {
            DB::rollBack();
            dd($e);
            return ['error' => $e->getMessage()];
        } catch (\Exception $e) {
            DB::rollBack();
            dd($e);
            return ['error' => $e->getMessage()];
        }


    }

    public function createGroup(array $createData)
    {
        $this->restApiName = self::TENCENT_REST_APIS['createGroup'];
        $baseApiHost = $this->getTencentImRestApiBaseHost();

        //TODO 做单点登录，避免并发
        $params = [
            //TODO 新建群默认群主为APP管理员
            'Owner_Account' => config('im.identifier'),
            'Type' => TencentImGroup::IM_GROUP_RAW_TYPE_ChatRoom,
            'Name' => TencentImGroup::getGroupIndex(),
        ];

        $apiResult = $this->requestApi($baseApiHost, $params);


        dd($apiResult);
    }


    /**
     * 构建添加群数组
     * @param int $groupCount
     * @return mixed
     */
    private function generateCreateGroupData(int $groupCount)
    {
        $groupStartIndex = TencentImGroup::getGroupIndex();
        $groupEndIndex = $groupStartIndex + $groupCount;
        for ($i = $groupStartIndex; $i < $groupEndIndex; $i++) {
            $item = [
                //TODO 新建群默认群主为APP管理员
                'Owner_Account' => config('im.identifier'),
                'Type' => TencentImGroup::IM_GROUP_RAW_TYPE_ChatRoom,
                'Name' => $i,
            ];
            $this->createGroup($item);
            $params[] = $item;

        }
        unset($item);
        return $params;
    }

}
