<?php
/**
 *
 * @author：llbjj
 * @DateTime：2022/9/5 14:33
 * @Description：企业微信一系列操作
 *
 */
namespace Application\Service\Extension\Wechat;

use Application\Service\BaseService;
use Application\Service\Exceptions\InvalidArgumentException;
use Application\Service\Extension\Laminas;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use EasyWeChat\Kernel\Messages\TextCard;
use EasyWeChat\Kernel\Support\Collection;
use GuzzleHttp\Exception\GuzzleException;
use Interop\Container\ContainerInterface;
use Laminas\Stdlib\ArrayUtils;
use Psr\Http\Message\ResponseInterface;

class WechatWork extends BaseService {
    protected $workApp;
    public function __construct(ContainerInterface $container)
    {
        parent::__construct($container);
        $this->workApp = $this->LocalService()->wechat->getWorkApp();
    }

    private function checkOpenWork() {
        return $this->LocalService()->config['isOpenWechatWork'] ? true : false;
    }

    /**
     * Notes: 给用户发送文本消息，暂时主要是用来错误信息
     * User: llbjj
     * DateTime: 2022/9/19 15:12
     *
     * @param string $sendMsg
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
     */
    public function sendMesToUser(array $sendMsg = [], string $userId = '') {
        if( !self::checkOpenWork() ) return '';
        if(!empty($sendMsg['title']) && !empty($sendMsg['description'])) {
            $agentConfig = $this->LocalService()->config['work']['app']['agent'] ?? [];
            if(empty($agentConfig)) throw new InvalidArgumentException('请配置企业微信应用信息！');

            $agent_id     = array_keys($agentConfig)[0];
            $agent_secret = array_values($agentConfig)[0];

            $this->workApp->config->set('agent_id', $agent_id);
            $this->workApp->config->set('secret', $agent_secret);

            $msgContent = new TextCard($sendMsg);
            // print_r($this->workApp->agent->list());exit;
            self::handleResult($this->workApp->messenger->message($msgContent)->toUser($userId ?: $this->LocalService()->config['work']['defaultUser'])->send());
        }

    }

    /**
     * Notes: 创建部门ID
     * User: llbjj
     * DateTime: 2022/9/5 15:15
     *
     * @param $deptId           部门ID，必须指定，不能自动生成，方便和内容系统有对应的关系
     * @param $deptName         部门名称
     * @param string $deptType  部门类型，不同给类型，id号会有不同的前缀
     * @param int $parentId     上级部门ID
     */
    public function saveDepartment($deptId, $deptName, $deptType = 'item', $parentId = 1, $parentType = 'item', $order = 1) {
        if( !self::checkOpenWork() ) return '';
        $isExist = $this->isExistDepartment($deptType, $deptId);
        $deptId = self::_getDepartmentId($deptType, $deptId);
        $deptData = [
            'name' => $deptName,
            'parentid' => $parentId != 1 ? self::_getDepartmentId($parentType, $parentId) : 1,
            'order' => $order
        ];

        $isExist
            ? $this->handleResult($this->workApp->department->update($deptId, $deptData))
            : $this->handleResult($this->workApp->department->create(ArrayUtils::merge($deptData, ['id' => $deptId]))) ;
    }

    /**
     * Notes: 删除部门
     * User: llbjj
     * DateTime: 2024/5/29 9:47
     *
     * @param $deptId
     * @param $deptType
     * @return string|void
     * @throws InvalidConfigException
     */
    public function delDepartment($deptId, $deptType = 'item') {
        if( !self::checkOpenWork() ) return '';
        $isExist = $this->isExistDepartment($deptType, $deptId);
        $deptId = self::_getDepartmentId($deptType, $deptId);

        if($isExist) $this->handleResult($this->workApp->department->delete($deptId));
    }

    /**
     * Notes: 检测部门是否存在
     * User: llbjj
     * DateTime: 2022/9/5 17:51
     *
     * @param $deptId
     * @return bool
     * @throws InvalidConfigException
     */
    public function isExistDepartment($deptType = 'item', $deptId) {
        if( !self::checkOpenWork() ) return '';
        $result = $this->workApp->department->simpleList($this->_getDepartmentId($deptType, $deptId));
        if(!in_array($result['errcode'], [0, 60123])) throw new InvalidArgumentException($result['errmsg']);

        return $result['errcode'] == 0 ;
    }

    /**
     * Notes:
     * User: llbjj
     * DateTime: 2022/9/5 15:08
     *
     * @param $userID       成员ID
     * @param $userName     成员姓名
     * @param $mobile       手机号
     * @param $depatmentID  所属部门ID（中心ID）
     */
    public function saveUser($userID, $userName, $mobile, $depatmentID, $enable = 1, string $userServiceName = 'signatoryUser') {
        if( !self::checkOpenWork() ) return '';
        // 操作方法
        $isExist = $this->isExistUser($userID, $userServiceName);
        $userID = self::_getUserId($userID);
        $userData = [
            'name' => $userName,
            'mobile' => $mobile,
            'enable' => $enable,
            'department' => [$this->_getDepartmentId('itemsig', $depatmentID)]
        ];

        $isExist
            ?
            $this->handleResult($this->workApp->user->update($userID, $userData))
            :
            $this->handleResult($this->workApp->user->create(ArrayUtils::merge($userData, ['userid' => $userID])));
        return $isExist;
    }

    /**
     * Notes: 获取用户信息
     * User: llbjj
     * DateTime: 2022/9/5 17:42
     *
     * @param $userID
     * @return array|Collection|object|ResponseInterface|string
     * @throws InvalidConfigException
     */
    public function getUser(int $userID) {
        if( !self::checkOpenWork() ) return '';
        // 通过应用获取用户信息
        return $this->workApp->user->get(self::_getUserId($userID));
    }

    /**
     * Notes: 检测用户是否存在
     * User: llbjj
     * DateTime: 2022/9/5 17:42
     *
     * @param int $userID
     * @param string $userServiceName
     * @return bool|string
     * @throws GuzzleException
     * @throws InvalidConfigException
     */
    public function isExistUser(int $userID, string $userServiceName = 'signatoryUser') {
        if( !self::checkOpenWork() ) return '';
        $telFieldName = $userServiceName == 'patient' ? 'patient_tel' : 'user_tel';

        // 根据用户id获取企业微信的所有用户id
        $workUserList = $this->handleResult($this->workApp->user->httpPostJson('cgi-bin/user/list_id', [ 'limit' => 10000]));
        $workUserList = array_column($workUserList['dept_user'], 'userid');

        if(! in_array($this->_getUserId($userID), $workUserList)) return false;

        // 获取人员的手机号
        $mobile = $this->LocalService()->{$userServiceName}->getOneFieldVal($telFieldName, ['id'=> $userID]);
        if(!$mobile) return true;

        $result = $this->workApp->user->mobileToUserId($mobile);
        if(!isset($result['userid'])) return true;

        if($this->_getUserId($userID) == $result['userid']) return true;

        throw new InvalidArgumentException('手机号重复！');
    }

    /**
     * Notes: 设置企业微信人员的状态
     * User: llbjj
     * DateTime: 2022/9/5 16:17
     *
     * @param int $userId
     * @param int $enable   1、启用；0、禁用
     * @throws InvalidConfigException
     * @throws GuzzleException
     */
    public function setUserEnable(int $userId, $enable = 1, string $userServiceName = 'signatoryUser') {
        if( !self::checkOpenWork() ) return '';
        if($this->isExistUser($userId, $userServiceName)) {
            self::handleResult($this->workApp->user->update(self::_getUserId($userId), [
                'enable' => $enable
            ]));
        }
    }

    /**
     * Notes: 删除企业微信账户信息
     * User: llbjj
     * DateTime: 2022/9/8 15:57
     *
     * @param int $userId
     * @throws InvalidConfigException
     * @throws GuzzleException
     */
    public function delUser(int $userId, string $userServiceName = 'signatoryUser') {
        if( !self::checkOpenWork() ) return '';
        if($this->isExistUser($userId, $userServiceName)) {
            self::handleResult($this->workApp->user->delete(self::_getUserId($userId)));
        }
    }

    /**
     * Notes: 添加【联系我】
     * User: llbjj
     * DateTime: 2022/9/9 9:06
     *
     * @param int $userId
     * @return array|bool
     * @throws InvalidConfigException
     * @throws GuzzleException
     */
    public function addContactWay(int $userId) {
        if( !self::checkOpenWork() ) return '';
        $type = 1;
        $scene = 1;
        $config = [
            'style' => 1,
            'remark' => 'SDM原始数据管理',
            'skip_verify' => true,
            'state' => 'sdmSignatoryUser',
            'user' => [self::_getUserId($userId)],
        ];
        if(!$this->LocalService()->config['work']['app']['contact_secret']) return '';
        $this->workApp->config->set('secret', $this->LocalService()->config['work']['app']['contact_secret']);
        return self::handleResult($this->workApp->contact_way->create($type, $scene, $config));
    }

    /**
     * Notes: 删除联系我配置
     * User: llbjj
     * DateTime: 2022/9/9 8:58
     *
     * @param String $configID
     */
    public function delContactWay(String $configID) {
        if( !self::checkOpenWork() ) return '';
        if(!$this->LocalService()->config['work']['app']['contact_secret']) return '';
        $this->workApp->config->set('secret', $this->LocalService()->config['work']['app']['contact_secret']);
        self::handleResult($this->workApp->contact_way->delete($configID));
    }

    /**
     * Notes: 获取企业微信部门ID（包含前缀）
     * User: llbjj
     * DateTime: 2022/9/5 15:32
     *
     * @param $deptType         部门类型 ['item', 'itemsig']
     * @param $departmentId     部门指定ID
     * @return mixed|string
     */
    private function _getDepartmentId($deptType, $departmentId) {
        $departmentIdPrefix = $this->LocalService()->config['work']['departmentIdPrefix'][$deptType];
        return $departmentIdPrefix.$departmentId;
    }

    /**
     * Notes: 获取企业微信人员ID（包含前缀）
     * User: llbjj
     * DateTime: 2022/9/5 16:09
     *
     * @param $userId
     * @return string
     */
    private function _getUserId($userId) {
        $userIdPrefix = $this->LocalService()->config['work']['userIdPrefix'];
        return $userIdPrefix.$userId;
    }

    /**
     * Notes: 统一处理返回信息
     * User: llbjj
     * DateTime: 2022/9/8 18:54
     *
     * @param array $result
     * @return bool
     */
    private function handleResult(array $result) {
        if($result['errcode'] !== 0) throw new InvalidArgumentException($result['errmsg'], $result['errcode']);
        return $result;
    }
}