<?php
namespace JinDouYun\Controller;

use AlibabaCloud\SDK\Dingtalk\Vworkflow_1_0\Models\GetProcessConfigResponseBody\result\handSignConf;
use JinDouYun\Cache\ShopCache;
use JinDouYun\Cache\SupplierCache;
use JinDouYun\Dao\Enterprise\DEnterprise;
use JinDouYun\Dao\Shop\DShopKey;
use JinDouYun\Model\Enterprise\MEnterprise;
use JinDouYun\Model\System\MBasicSetup;
use JinDouYun\Model\System\MModule;
use JinDouYun\Model\Shop\MShop;
use Mall\Framework\Core\StatusCode;
use Mall\Framework\Factory;
use Mall\Framework\Core\Jwt;
use Mall\Framework\Core\ErrorCode;

use JinDouYun\Cache\EnterpriseCache;
use JinDouYun\Cache\RoleAclCache;
use JinDouYun\Cache\SysAreaChinaCache;

use JinDouYun\Model\SysAreaChina\MSysAreaChina;

class BaseController
{

    /** @var  \Mall\Framework\Core\Request $request */
    protected $request;

    /** @var  \Mall\Framework\Core\Cache $cache */
    protected $cache;

    /**
     * @var int
     */
    protected $onlineUserId;

    /**
     * @var int
     */
    protected $onlineEnterpriseId;

    /**
     * @var string
     */
    protected $authorization;

    /**
     * @var string
     */
    protected $token;

    /**
     * @var string
     */
    protected $areaCode;

    /**
     * @var string 店铺token
     */
    private $shopToken = '';

    /**
     * @var int 供应商id
     */
    protected $supplierId = null;//TODO

    /**
     * @var string
     */
    protected $supplierToken = '';

    /**
     * @var int
     */
    protected $shopId = 0;

    /**
     * BaseController constructor.
     * @param bool $isCheckAcl
     * @param false $isMustLogin
     * @param bool $checkToken
     * @param false $getAreaCode
     * @param bool $checkShopToken
     * @param bool $checkSupplierToken
     */
    public function __construct(
        $isCheckAcl = true,
        $isMustLogin = false,
        $checkToken = true,
        $getAreaCode=false,
        $checkShopToken = true,
        $checkSupplierToken = true
    ){
        $this->request = Factory::request();
        //$this->cache = Factory::cache();

        if($isMustLogin){
            self::getUserIdByAuthorization();
        }

        if($checkToken){
            self::getEnterpriseIdByToken();
        }

        if($isCheckAcl){
//            self::checkAcl();
        }

        if ($getAreaCode) {
            self::getAreaCode();
        }
        if ($checkShopToken){
            self::getShopIdByShopToken();
        }
        if ($checkSupplierToken){
            self::getSupplierIdBySupplierToken();
        }
    }

    /**
     * #777每请求一次接口刷新一次Authorization 没有请求接口2小时 Authorization过期 需要重新登录
     * 根据Authorization获取userCenterId
     *
     * return int
     */
    public function getUserIdByAuthorization()
    {
        $authorization = $this->request->getServerParam('HTTP_AUTHORIZATION');
        if(empty($authorization)) {
            $this->sendOutput('未登录', ErrorCode::$notAllowToken);
        }

        try {
            $jwt_data = JWT::decode($authorization, SITE_SECRET, array('HS256'));

            if (empty($jwt_data) || $jwt_data->expireTime < time()) {
//                $this->sendOutput('登陆用户过期', ErrorCode::$loginedexpire);
                /*
                    $referurl = $this->request->getServerParam('REQUEST_URI');
                    $loginUrl = '?m=member&c=login&a=login&referurl=' . DOMAIN_PROJECT . $referurl;
                    header('Location:' . $loginUrl);
                */
            }
            $this->onlineUserId = intval($jwt_data->uid);
            $this->authorization = $authorization;

        } catch (\Exception $e) {
            $this->sendOutput('无效的Authorization', ErrorCode::$notAllowToken);
        }
    }

    /**
     * Doc: (des="根据SHOP_TOKEN获取店铺id")
     * User: XMing
     * Date: 2020/12/2
     * Time: 10:03 上午
     */
    public function getShopIdByShopToken($Token = '')
    {
        $shopToken = $this->request->getServerParam('HTTP_SHOP_TOKEN');
        if (empty($shopToken)){
            $shopToken = $Token;
            if (empty($shopToken)){
                return;
            }
        }

        $this->shopToken = $shopToken;
        $objShopCache = new ShopCache();
        if (empty($this->onlineEnterpriseId)){
            $token = $this->request->getServerParam('HTTP_TOKEN');
            $this->token = $token;
            if (!empty($this->token)){
                $objEnterpriseCache = new EnterpriseCache();
                $this->onlineEnterpriseId = intval($objEnterpriseCache->getEnterpriseIdByToken($token));
            }
        }
        $objMShop=new MShop($this->onlineEnterpriseId);
        $this->shopId=$objMShop->getShopid($this->onlineEnterpriseId,$this->shopToken)[0]['id'];
      ;

//        $this->shopId = intval($objShopCache->getShopToken(10,$this->shopToken));
        if (empty($this->shopId)){
            $this->sendOutput('店铺不存在',ErrorCode::$notAllowAccess);
        }
    }

    public function getSupplierIdBySupplierToken()
    {
        $supplierToken = $this->request->getServerParam('HTTP_SUPPLIER_TOKEN');
        if (empty($supplierToken)){
            return;
        }
        $this->supplierToken = $supplierToken;
        $objSupplierCache = new SupplierCache();
        $this->supplierId = intval($objSupplierCache->getSupplierToken($this->onlineEnterpriseId,$this->supplierToken));
        if (empty($this->supplierId)){
            $this->sendOutput('供应商不存在',ErrorCode::$notAllowAccess);
        }
    }

    /**
     * 根据企业token获取企业id enterpriseId
     * return int
     * @param bool $checkExists
     */
    public function getEnterpriseIdByToken($checkExists = true)
    {
        $token = $this->request->getServerParam('HTTP_TOKEN');
        $this->token = $token;
        if(!$this->token && $checkExists) {
            $this->sendOutput('token为空', ErrorCode::$notAllowToken);
        }
        // 先从Cache中根据token找id
        $objEnterpriseCache = new EnterpriseCache();
        $this->onlineEnterpriseId = intval($objEnterpriseCache->getEnterpriseIdByToken($token));
       // 如果没有就从数据库中找id
        if(empty($this->onlineEnterpriseId)){
          $objMEnterprise = new MEnterprise();
          $enterpriseId = $objMEnterprise->getEnterpriseIdByToken($token);
          if(!$enterpriseId->isSuccess()){
              $this->sendOutput($enterpriseId->getData(), $enterpriseId->getErrorCode());
          }
          $enterpriseId = $enterpriseId->getData();
          $this->onlineEnterpriseId = intval($enterpriseId);
        }

        // 以上都没有则企业不存在
        if( empty($this->onlineEnterpriseId) && $checkExists){
            $this->sendOutput('当前企业不存在', ErrorCode::$notAllowAccess);
        }

        $objEnterpriseCache->enterpriseIdAndTokenCache($this->onlineEnterpriseId, $token);
    }

    public function getAreaCode() {
        $location = $this->request->getServerParam('HTTP_LOCATION');
        if (empty($location)) {
            $this->areaCode = '';
            return;
        }

        $areaArr = json_decode(base64_decode($location),true);
        if (is_string($areaArr)) {
            $areaArr = json_decode($areaArr,true);
        }
        if(empty($areaArr)){
            $areaArr = [
                'provinceName' => '陕西省',
                'cityName'     => '西安市',
                'districtName' => '莲湖区'
            ];
        }
        foreach($areaArr as &$value){
            if(empty($value)){
                $value = '';
            }
        }

        switch($areaArr['cityName']){
            case '北京市':
                $areaArr['provinceName'] = '北京市';
                break;
            case '重庆市':
                $areaArr['provinceName'] = '重庆市';
                break;
            case '天津市':
                $areaArr['provinceName'] = '天津市';
                break;
            case '上海市':
                $areaArr['provinceName'] = '上海市';
                break;
        }
//        V($areaArr);

        $this->areaCode = '';
        $objMSysAreaChina = new MSysAreaChina();
        $modelResult = $objMSysAreaChina->getCodeByName($areaArr);
        if(!$modelResult->isSuccess()){
            $this->sendOutput($modelResult->getData(), $modelResult->getErrorCode());
        }
        $areaData = $modelResult->getData();
        foreach($areaData as $value){
            $this->areaCode = !empty($this->areaCode) ? $this->areaCode.'-'.$value : $this->areaCode.$value;
        }
    }
    /**
     * 校验权限,当前登录用户是否可操作当前企业
     */
    public function checkAcl() {
        if(!$this->onlineUserId) {
            $this->sendOutput('请登录', ErrorCode::$notAllowToken);
        }

        if(!$this->onlineEnterpriseId) {
            $this->sendOutput('请选择企业', ErrorCode::$notAllowToken);
        }

        //获取用户与企业的关联关系
        $objEnterpriseCache = new EnterpriseCache();
        $enterpriseIds = $objEnterpriseCache->getUserCenterIdAndEnterpriseIds($this->onlineUserId);

        //用户与企业不存在关联,则无权限
        if(!isset($enterpriseIds[$this->onlineEnterpriseId])){
            $this->sendOutput('没有权限操作', ErrorCode::$notAllowAccess);
        }

        //如果是创建者,则超级管理员,无限权限
        if($enterpriseIds[$this->onlineEnterpriseId] == StatusCode::$roleType['admin']) {
            return true;
        }

        //员工,获取其在企业所属的角色组id
        $objRoleAclCache = new RoleAclCache();
        $roleId = $objRoleAclCache->getRoleIdOfStaff($this->onlineEnterpriseId, $this->onlineUserId);
        if(!$roleId){
            $this->sendOutput('请联系管理员获取角色', ErrorCode::$notAllowAccess);
        }

        //查询是否为超级管理员
        $cacheResult = $objRoleAclCache->getAdministrator($this->onlineEnterpriseId, $roleId);
        if($cacheResult){
            //是超级管理员
            return true;
        }

        self::accessCheck($roleId);
    }

    /**
     * 系统核心权限控制部分
     * @param array $aclList
     * @return bool
     */
    public function accessCheck($roleId)
    {
        $moduleName = strtolower($this->request->getModule());
        $controllerName = strtolower($this->request->param('c'));
        $actionName = strtolower($this->request->getAction());

        if (!$moduleName || !$controllerName || !$actionName) {
            self::sendOutput('非法的请求', ErrorCode::$notAllowAccess);
        }

        $accessUrl = $moduleName . DS . $controllerName . DS . $actionName;
        //过滤是否验证权限
        $objRoleAclCache = new RoleAclCache();
        $result = $objRoleAclCache->getAuthority($accessUrl);
        if(!$result){
            return true;
        }
        //搜索的直接放行
        if(strpos($actionName,'search') !== false) {
            return true;
        }
        $cacheResult = $objRoleAclCache->getAuthorityBindRole($this->onlineEnterpriseId, $roleId, $accessUrl);
        if(!$cacheResult){
            $objMModule = new MModule();
            $moduleName =(string) $objMModule->getModuleNameByUri($accessUrl);
            self::sendOutput('没有权限操作,'.$moduleName, ErrorCode::$notHaveAclAccess);
        }
        return true;
    }

    /**
     * 项目全局返回json格式
     * @param $data
     * @param int $errorcode
     * @param array $pageData
     */
    public function sendOutput($data, $errorcode = 0, $pageData = [])
    {
        $errorcode = intval($errorcode);

        if ($errorcode) {
            $sendMessage = [
                'state' => false,
                'data' => $data,
                'errorcode' => $errorcode
            ];
        } else {
            $sendMessage = [
                'state' => true,
                'data' => $data,
                'errorcode' => $errorcode
            ];
        }
        $sendMessage = array_merge($sendMessage, $pageData);

        if($sendMessage['errorcode'] == ErrorCode::$dberror){
            $moduleName = strtolower($this->request->getModule());
            $controllerName = strtolower($this->request->param('c'));
            $actionName = strtolower($this->request->getAction());
            $accessUrl = $moduleName . DS . $controllerName . DS . $actionName;
//            file_put_contents('../apps/logs/sqlerror.log', date('Y-m-d H:i:s').'-'.$accessUrl.'-'.var_export($sendMessage['data'], true) . PHP_EOL, FILE_APPEND);
        }

        if(empty($sendMessage['data']) && !isset($sendMessage['pageTotal'])){
            exit(json_encode($sendMessage, JSON_UNESCAPED_UNICODE|JSON_FORCE_OBJECT));
        }
        exit(json_encode($sendMessage, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 检查手机号格式
     * @param $mobile
     */
    public function checkMobile($mobile){
        $checkMobile = isMobile($mobile);
        if(!$checkMobile){
            self::sendOutput('手机格式不正确', ErrorCode::$paramError);
        }
    }



    public function pr($var, $int = '')
    {
        $template = PHP_SAPI !== 'cli' ? '<pre>%s</pre>' : "\n%s\n";
        printf($template, print_r($var, true));
        exit($int);

    }

    /**
     *获取AccessToken
     * @return bool|string
     */
    public function AccessToken()
    {
        $this->shopKey = new DShopKey('default');

        $this->shopKey->setTable($this->shopKey->get_Table().'_'.$this->onlineEnterpriseId);

        $data = $this->shopKey->get(['shop_id' => $this->shopId]);
        $data = [
            'corpid' => $data['corpid'],
            'ssoSecret' => $data['ssoSecred']
        ];
        $res = $this->post_json('https://api.dingtalk.com/v1.0/oauth2/ssoAccessToken', json_encode($data));
        $res = json_decode($res);
        return $res->access_token;
    }

    /**
     * 获取免登入凭证
     * @return bool|string
     */
    public function voucher($shopId = '', $EnterpriseId = '')
    {
        $this->shopKey = new DShopKey('default');

        $onlineEnterpriseId = $this->onlineEnterpriseId ? $this->onlineEnterpriseId : $EnterpriseId;
        $shopId = $this->shopId ? $this->shopId : $shopId;


        $basic = new MBasicSetup($onlineEnterpriseId);
        $data = $basic->getBasicSetup($onlineEnterpriseId)->getData();
//        $data = $this->shopKey->get(['enterprise_id' => $onlineEnterpriseId]);

        if (isset($data['basicData']['appKey']) and isset($data['basicData']['appSecret'])){
            if (empty($data['basicData']['appKey']) || empty($data['basicData']['appSecret'])){
                self::sendOutput('请完善配置钉钉apikey', ErrorCode::$paramError);
            }
        }else{
            self::sendOutput('请配置钉钉apikey', ErrorCode::$paramError);
        }

        $res = $this->curl_get('https://oapi.dingtalk.com/gettoken?appkey='.$data['basicData']['appKey'].'&appsecret='.$data['basicData']['appSecret']);
        $res = json_decode($res);
        return $res->access_token;
    }

    /**
     * group_key
     * @return mixed
     */
    public function group_key($id)
    {
        $group_key = $this->post_json('https://oapi.dingtalk.com/topapi/attendance/groups/idtokey?access_token='.$this->voucher(),json_encode(['group_id' => $id]));
        $group_key = json_decode($group_key);
        if ($group_key->errcode > 0){
            parent::sendOutput($group_key->errmsg, 1);
        }
        return $group_key->result;
    }



    public function curl_get($url, &$httpCode = 0)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        //不做证书校验,部署在linux环境下请改为true
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        $file_contents = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return $file_contents;
    }

    public function post_json($url , $params = array()){
        //$data_string = json_encode($params,JSON_UNESCAPED_UNICODE);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        curl_setopt(
            $ch, CURLOPT_HTTPHEADER,
            array(
                'Content-Type: application/json'
            )
        );

        $data = curl_exec($ch);
        curl_close($ch);
        return ($data);
    }

    public function getRandPass($length = 8)
    {
        $password = '';
        $chars = "0123456789";

        $char_len = strlen($chars);

        for ($i = 0; $i <= $length; $i++) {
            $loop = mt_rand(0, ($char_len - 1));
            $password .= $chars[$loop];
        }
        return $password;

    }
}